Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions client/functions/robots.txt.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import {
buildTargetUrl,
createPlainApiBaseErrorResponse,
getBackendUrl,
} from "./_shared";

// 代理 /robots.txt 到 Workers 后端
// 仅允许 GET/HEAD,避免成为开放 method 转发器
export const onRequest: PagesFunction<{ API_BASE: string }> = async (context) => {
const method = context.request.method.toUpperCase();
if (method !== "GET" && method !== "HEAD") {
return new Response("Method Not Allowed", {
status: 405,
headers: { Allow: "GET, HEAD", "Content-Type": "text/plain; charset=utf-8" },
});
}

const backend = getBackendUrl(context.env);
if (!backend) {
return createPlainApiBaseErrorResponse();
}

const target = buildTargetUrl(backend, context.request);
// 不透传客户端 headers,避免泄漏 Cookie / Authorization 给后端代理链路
const res = await fetch(target, {
method,
headers: { Accept: "text/plain" },
});
return new Response(res.body, {
status: res.status,
headers: res.headers,
});
Comment thread
coderabbitai[bot] marked this conversation as resolved.
};
33 changes: 33 additions & 0 deletions client/functions/sitemap.xml.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import {
buildTargetUrl,
createPlainApiBaseErrorResponse,
getBackendUrl,
} from "./_shared";

// 代理 /sitemap.xml 到 Workers 后端
// 仅允许 GET/HEAD,避免成为开放 method 转发器
export const onRequest: PagesFunction<{ API_BASE: string }> = async (context) => {
const method = context.request.method.toUpperCase();
if (method !== "GET" && method !== "HEAD") {
return new Response("Method Not Allowed", {
status: 405,
headers: { Allow: "GET, HEAD", "Content-Type": "text/plain; charset=utf-8" },
});
}

const backend = getBackendUrl(context.env);
if (!backend) {
return createPlainApiBaseErrorResponse();
}

const target = buildTargetUrl(backend, context.request);
// 不透传客户端 headers,避免泄漏 Cookie / Authorization 给后端代理链路
const res = await fetch(target, {
method,
headers: { Accept: "application/xml, text/xml" },
});
return new Response(res.body, {
status: res.status,
headers: res.headers,
});
};
2 changes: 2 additions & 0 deletions client/src/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ const AdminPages = lazy(() => import("@/pages/admin/pages").then((m) => ({ defau
const AdminComments = lazy(() => import("@/pages/admin/comments").then((m) => ({ default: m.AdminComments })));
const AdminMedia = lazy(() => import("@/pages/admin/media").then((m) => ({ default: m.AdminMedia })));
const AdminAnalytics = lazy(() => import("@/pages/admin/analytics").then((m) => ({ default: m.AdminAnalytics })));
const AdminSeo = lazy(() => import("@/pages/admin/seo").then((m) => ({ default: m.AdminSeo })));
const PrivacyPage = lazy(() => import("@/pages/privacy").then((m) => ({ default: m.PrivacyPage })));
const DynamicPage = lazy(() => import("@/pages/dynamic-page").then((m) => ({ default: m.DynamicPage })));
const NotFoundPage = lazy(() => import("@/pages/not-found").then((m) => ({ default: m.NotFoundPage })));
Expand Down Expand Up @@ -165,6 +166,7 @@ export function App() {
<Route path="/admin/comments"><AdminComments /></Route>
<Route path="/admin/media"><AdminMedia /></Route>
<Route path="/admin/analytics"><AdminAnalytics /></Route>
<Route path="/admin/seo"><AdminSeo /></Route>
<Route path="/admin"><AdminDashboard /></Route>
<Route><NotFoundPage /></Route>
</Switch>
Expand Down
2 changes: 2 additions & 0 deletions client/src/components/admin-layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
ImageIcon,
BarChart3,
HardDrive,
Sparkles,
Settings,
LogOut,
ExternalLink,
Expand Down Expand Up @@ -51,6 +52,7 @@ export function AdminLayout({ children }: AdminLayoutProps) {
items: [
{ href: "/admin/media", icon: ImageIcon, label: "媒体库" },
{ href: "/admin/analytics", icon: BarChart3, label: "数据分析" },
{ href: "/admin/seo", icon: Sparkles, label: "SEO 优化" },
{ href: "/admin/backup", icon: HardDrive, label: "安全备份" },
],
},
Expand Down
Loading
Loading