Files
2026-03-18 18:57:58 +08:00

63 lines
2.2 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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<Response>) {
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 });
}