53 lines
1.8 KiB
TypeScript
53 lines
1.8 KiB
TypeScript
import type { NextRequest } from "next/server"
|
|
import { backendInternalUrl } from "@/lib/backend-internal-url"
|
|
|
|
type ProxyBackendRequestOptions = {
|
|
method?: string
|
|
forwardRequestBody?: boolean
|
|
}
|
|
|
|
export async function proxyBackendRequest(
|
|
request: NextRequest,
|
|
backendPath: string,
|
|
options: ProxyBackendRequestOptions = {},
|
|
): Promise<Response> {
|
|
const method = options.method ?? request.method
|
|
const headers = new Headers()
|
|
for (const [key, value] of request.headers.entries()) {
|
|
const lower = key.toLowerCase()
|
|
if (lower === "host" || lower === "connection") continue
|
|
headers.set(key, value)
|
|
}
|
|
|
|
const fetchInit: RequestInit & { duplex?: "half" } = {
|
|
method,
|
|
headers,
|
|
cache: "no-store",
|
|
}
|
|
|
|
const forwardRequestBody = options.forwardRequestBody ?? !["GET", "HEAD"].includes(method)
|
|
if (forwardRequestBody && request.body) {
|
|
fetchInit.body = request.body
|
|
fetchInit.duplex = "half"
|
|
}
|
|
|
|
try {
|
|
const upstream = await fetch(`${backendInternalUrl()}${backendPath}`, fetchInit)
|
|
const responseHeaders = new Headers()
|
|
const contentType = upstream.headers.get("Content-Type")
|
|
const contentDisposition = upstream.headers.get("Content-Disposition")
|
|
if (contentType) responseHeaders.set("Content-Type", contentType)
|
|
if (contentDisposition) responseHeaders.set("Content-Disposition", contentDisposition)
|
|
const databaseOutcome = upstream.headers.get("X-System-Database-Outcome")
|
|
if (databaseOutcome) responseHeaders.set("X-System-Database-Outcome", databaseOutcome)
|
|
|
|
return new Response(upstream.body, {
|
|
status: upstream.status,
|
|
headers: responseHeaders,
|
|
})
|
|
} catch (error) {
|
|
const message = error instanceof Error ? error.message : "Не удалось связаться с бекендом"
|
|
return Response.json({ error: message }, { status: 502 })
|
|
}
|
|
}
|