1
This commit is contained in:
parent
40fd0c2282
commit
4397369e35
@ -7,7 +7,7 @@ services:
|
||||
environment:
|
||||
DATABASE_URL: sqlite+aiosqlite:////app/data/palm_reading.db
|
||||
UPLOAD_DIR: /app/storage/uploads
|
||||
CORS_ORIGINS: '["http://127.0.0.1:3011","http://localhost:3011"]'
|
||||
CORS_ORIGINS: '["https://m.xclaw.ren","http://127.0.0.1:3011","http://localhost:3011"]'
|
||||
ports:
|
||||
- "8066:8000"
|
||||
volumes:
|
||||
|
||||
0
palm_reading.db
Normal file
0
palm_reading.db
Normal file
80
web/app/api/[...path]/route.ts
Normal file
80
web/app/api/[...path]/route.ts
Normal file
@ -0,0 +1,80 @@
|
||||
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;
|
||||
@ -2,16 +2,6 @@ import type { NextConfig } from "next";
|
||||
|
||||
const nextConfig: NextConfig = {
|
||||
reactStrictMode: true,
|
||||
async rewrites() {
|
||||
const apiInternalUrl = process.env.API_INTERNAL_URL || "http://127.0.0.1:8000";
|
||||
|
||||
return [
|
||||
{
|
||||
source: "/api/:path*",
|
||||
destination: `${apiInternalUrl}/api/:path*`,
|
||||
},
|
||||
];
|
||||
},
|
||||
};
|
||||
|
||||
export default nextConfig;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user