81 lines
2.1 KiB
TypeScript
81 lines
2.1 KiB
TypeScript
import { NextRequest } from "next/server";
|
|
|
|
export const runtime = "nodejs";
|
|
export const dynamic = "force-dynamic";
|
|
|
|
const HOP_BY_HOP_HEADERS = new Set([
|
|
"connection",
|
|
"keep-alive",
|
|
"proxy-authenticate",
|
|
"proxy-authorization",
|
|
"te",
|
|
"trailer",
|
|
"transfer-encoding",
|
|
"upgrade",
|
|
"host",
|
|
]);
|
|
|
|
type RouteContext = {
|
|
params: Promise<{ path: string[] }>;
|
|
};
|
|
|
|
function getApiInternalUrl() {
|
|
return (process.env.API_INTERNAL_URL || "http://127.0.0.1:8000").replace(/\/$/, "");
|
|
}
|
|
|
|
function buildHeaders(request: NextRequest) {
|
|
const headers = new Headers();
|
|
request.headers.forEach((value, key) => {
|
|
if (!HOP_BY_HOP_HEADERS.has(key.toLowerCase())) {
|
|
headers.set(key, value);
|
|
}
|
|
});
|
|
return headers;
|
|
}
|
|
|
|
async function proxy(request: NextRequest, context: RouteContext) {
|
|
const { path } = await context.params;
|
|
const apiPath = path.join("/");
|
|
const targetUrl = new URL(`/api/${apiPath}${request.nextUrl.search}`, getApiInternalUrl());
|
|
const method = request.method.toUpperCase();
|
|
const hasBody = !["GET", "HEAD"].includes(method);
|
|
|
|
try {
|
|
const upstream = await fetch(targetUrl, {
|
|
method,
|
|
headers: buildHeaders(request),
|
|
body: hasBody ? await request.arrayBuffer() : undefined,
|
|
cache: "no-store",
|
|
});
|
|
|
|
const responseHeaders = new Headers(upstream.headers);
|
|
responseHeaders.delete("content-encoding");
|
|
responseHeaders.delete("content-length");
|
|
|
|
return new Response(upstream.body, {
|
|
status: upstream.status,
|
|
statusText: upstream.statusText,
|
|
headers: responseHeaders,
|
|
});
|
|
} catch (error) {
|
|
console.error("API proxy failed", {
|
|
target: targetUrl.toString(),
|
|
error: error instanceof Error ? error.message : String(error),
|
|
});
|
|
|
|
return Response.json(
|
|
{
|
|
detail: "后端服务暂时不可用,请检查 API_INTERNAL_URL 或后端容器状态。",
|
|
target: targetUrl.origin,
|
|
},
|
|
{ status: 502 },
|
|
);
|
|
}
|
|
}
|
|
|
|
export const GET = proxy;
|
|
export const POST = proxy;
|
|
export const PUT = proxy;
|
|
export const PATCH = proxy;
|
|
export const DELETE = proxy;
|