import { NextRequest } from "next/server"; const BACKEND_URL = process.env.BACKEND_URL || "http://localhost:8000"; export async function GET(req: NextRequest, ctx: { params: Promise<{ path: string[] }> }) { const { path } = await ctx.params; const url = new URL(req.url); const upstream = `${BACKEND_URL}/api/${path.join("/")}${url.search}`; return await safeUpstreamFetch(() => fetch(upstream, { headers: forwardHeaders(req) })); } export async function POST(req: NextRequest, ctx: { params: Promise<{ path: string[] }> }) { const { path } = await ctx.params; const url = new URL(req.url); const upstream = `${BACKEND_URL}/api/${path.join("/")}${url.search}`; const body = await req.text(); return await safeUpstreamFetch(() => fetch(upstream, { method: "POST", headers: { ...forwardHeaders(req), "content-type": req.headers.get("content-type") || "application/json" }, body }) ); } function forwardHeaders(req: NextRequest) { const h = new Headers(); const auth = req.headers.get("authorization"); if (auth) h.set("authorization", auth); return h; } async function forwardResponse(r: Response) { const headers = new Headers(r.headers); headers.delete("access-control-allow-origin"); return new Response(await r.arrayBuffer(), { status: r.status, headers }); } async function safeUpstreamFetch(doFetch: () => Promise) { const maxAttempts = 3; for (let i = 0; i < maxAttempts; i++) { try { const r = await doFetch(); return await forwardResponse(r); } catch (e: any) { const code = e?.cause?.code || e?.code; const retryable = code === "ECONNREFUSED" || code === "ENOTFOUND" || code === "EAI_AGAIN"; if (!retryable || i === maxAttempts - 1) { return new Response( JSON.stringify({ detail: "上游后端不可达(backend 容器可能正在重启或未就绪)。", error: String(code || e?.message || e) }), { status: 503, headers: { "content-type": "application/json; charset=utf-8" } } ); } await new Promise((r) => setTimeout(r, 200 * (i + 1))); } } return new Response(JSON.stringify({ detail: "unknown" }), { status: 503 }); }