import { defineMiddleware } from "astro:middleware"; import { COOKIE_LANG, localePath, resolvePreferredLocale } from "@app/i18n"; import { COOKIE_SESSION } from "@app/types"; import { authService } from "@app/trpc"; const SKIP_PREFIX = ["/api", "/_astro", "/favicon", "/robots", "/sitemap", "/llms"]; /** 需登录的基础路径(无 locale 前缀)。按需增删。 */ const PROTECTED_BASES = ["/dashboard", "/settings"] as const; const LOCALE_SEGMENTS = new Set(["zh-CN", "en"]); function shouldSkip(pathname: string): boolean { if (pathname !== "/" && pathname.includes(".")) return true; return SKIP_PREFIX.some((p) => pathname.startsWith(p)); } function basePathOf(pathname: string): string { const segs = pathname.split("/").filter(Boolean); const head = segs[0]; if (head && LOCALE_SEGMENTS.has(head)) { return `/${segs.slice(1).join("/")}`; } // 规范化前的 zh-cn 等在后续 redirect 处理,这里先按原样判断 if (head && head.toLowerCase() === "zh-cn") { return `/${segs.slice(1).join("/")}`; } return `/${segs.join("/")}`; } function isProtectedPath(pathname: string): boolean { const base = basePathOf(pathname); const normalized = base === "/" ? "/" : base.replace(/\/$/, ""); return PROTECTED_BASES.some((p) => normalized === p || normalized.startsWith(`${p}/`)); } function localeOf(pathname: string): "zh-CN" | "en" { const head = pathname.split("/").filter(Boolean)[0]; if (head === "en") return "en"; return "zh-CN"; } export const onRequest = defineMiddleware(async (context, next) => { const { request, url, cookies } = context; const path = url.pathname; if (shouldSkip(path)) { return next(); } // 裸 `/`:cookie → Accept-Language → /zh-CN 或 /en if (path === "/") { if (request.method !== "GET") return next(); const preferred = resolvePreferredLocale( cookies.get(COOKIE_LANG)?.value, request.headers.get("accept-language"), ); return context.redirect(localePath(preferred, "/")); } // 小写 zh-cn → 规范 zh-CN(保留 rest) const seg = path.split("/").filter(Boolean)[0]; if (seg && seg.toLowerCase() === "zh-cn" && seg !== "zh-CN") { const rest = path.slice(seg.length) || "/"; return context.redirect(`/zh-CN${rest === "/" ? "" : rest}`); } // 指定路由鉴权:无有效 session 则跳登录 if (request.method === "GET" && isProtectedPath(path)) { const token = cookies.get(COOKIE_SESSION)?.value; const user = await authService.getSessionUser(token); if (!user) { const locale = localeOf(path); const nextParam = encodeURIComponent(path + url.search); return context.redirect(`${localePath(locale, "/auth/login")}?next=${nextParam}`); } } const response = await next(); if (request.method === "GET") { response.headers.set("Vary", "Accept-Language"); } return response; });