/** * BFF 通用代理服务(仅服务端使用)。 * * 封装请求转发逻辑:构建请求头、注入 Bearer token、响应头透传过滤。 * proxy route handler 只负责编排:读路径 → 转发 → 401 重试 → 返回。 */ import type { NextRequest } from "next/server"; import { NextResponse } from "next/server"; /** 客户端 → 后端允许透传的请求头白名单(剔除 host / cookie / cf-* 等环境头)。 */ const FORWARD_HEADERS = [ "content-type", "accept", "accept-language", "idempotency-key", ]; /** * 构建转发给后端的请求头:白名单透传 + 注入 Bearer。 */ export function buildHeaders( req: NextRequest, token: string | null, ): Record { const headers: Record = {}; for (const key of FORWARD_HEADERS) { const v = req.headers.get(key); if (v) headers[key] = v; } if (token) headers["authorization"] = `Bearer ${token}`; return headers; } /** * 转发请求到后端目标地址。 * body 为已缓冲的 ArrayBuffer,可在 401 重试时复用。 */ export function forward( target: string, req: NextRequest, token: string | null, body: ArrayBuffer | null, ): Promise { const init: RequestInit = { method: req.method, headers: buildHeaders(req, token), cache: "no-store", }; if (body && req.method !== "GET" && req.method !== "HEAD") { init.body = body; } return fetch(target, init); } /** * 响应头透传,过滤 set-cookie(避免后端 cookie 干扰 BFF 的 cookie 管理)。 */ export function passthroughHeaders(src: Headers): Headers { const h = new Headers(); src.forEach((value, key) => { if (key.toLowerCase() === "set-cookie") return; h.set(key, value); }); return h; } /** * 构建后端目标 URL。 */ export function buildTargetUrl( backend: string, path: string[], search: string, ): string { return `${backend}/${path.join("/")}${search}`; } /** * 构造代理响应的 NextResponse。 */ export function proxyResponse(resp: Response): NextResponse { return new NextResponse(resp.body, { status: resp.status, statusText: resp.statusText, headers: passthroughHeaders(resp.headers), }); }