import { NextRequest, NextResponse } from "next/server"; const CSMS_INTERNAL_URL = process.env.CSMS_INTERNAL_URL ?? process.env.NEXT_PUBLIC_CSMS_URL ?? "http://localhost:3001"; /** 检查 CSMS 是否已完成初始化(有用户存在)。使用 cookie 缓存结果,避免每次请求都查询。 */ async function isInitialized(request: NextRequest): Promise<{ initialized: boolean; fromCache: boolean }> { // 读缓存 cookie const cached = request.cookies.get("helios_setup_done"); if (cached?.value === "1") { return { initialized: true, fromCache: true }; } try { const res = await fetch(`${CSMS_INTERNAL_URL}/api/setup`, { method: "GET", headers: { "Content-Type": "application/json" }, // 短超时,避免阻塞 signal: AbortSignal.timeout(3000), }); if (!res.ok) return { initialized: true, fromCache: false }; // 出错时放行,不阻止访问 const data = (await res.json()) as { initialized: boolean }; return { initialized: data.initialized, fromCache: false }; } catch { // 无法连接 CSMS 时放行,不强制跳转 return { initialized: true, fromCache: false }; } } export async function middleware(request: NextRequest) { const { pathname } = request.nextUrl; // /setup 页面:已初始化则跳转登录 if (pathname === "/setup") { const { initialized, fromCache } = await isInitialized(request); if (initialized) { return NextResponse.redirect(new URL("/login", request.url)); } const res = NextResponse.next(); if (!fromCache) { // 未初始化,确保缓存 cookie 不存在(若之前意外设置了) res.cookies.delete("helios_setup_done"); } return res; } // /dashboard 路由:检查 session,未登录跳转 /login if (pathname.startsWith("/dashboard")) { const { initialized, fromCache } = await isInitialized(request); // 未初始化,先去 setup if (!initialized) { const res = NextResponse.redirect(new URL("/setup", request.url)); if (!fromCache) res.cookies.delete("helios_setup_done"); return res; } const sessionCookie = request.cookies.get("helios.session_token") ?? request.cookies.get("__Secure-helios.session_token"); if (!sessionCookie) { const loginUrl = new URL("/login", request.url); loginUrl.searchParams.set("from", pathname); const res = NextResponse.redirect(loginUrl); if (!fromCache) res.cookies.set("helios_setup_done", "1", { path: "/", httpOnly: true, sameSite: "lax" }); return res; } const res = NextResponse.next(); if (!fromCache) res.cookies.set("helios_setup_done", "1", { path: "/", httpOnly: true, sameSite: "lax" }); return res; } // /login 路由:未初始化则跳转 /setup if (pathname === "/login") { const { initialized, fromCache } = await isInitialized(request); if (!initialized) { const res = NextResponse.redirect(new URL("/setup", request.url)); if (!fromCache) res.cookies.delete("helios_setup_done"); return res; } const res = NextResponse.next(); if (!fromCache) res.cookies.set("helios_setup_done", "1", { path: "/", httpOnly: true, sameSite: "lax" }); return res; } return NextResponse.next(); } export const config = { matcher: ["/setup", "/login", "/dashboard/:path*"], };