Spaces:
Paused
Paused
| import { NextRequest, NextResponse } from "next/server"; | |
| import { getServerSideConfig } from "@/app/config/server"; | |
| export async function handle( | |
| req: NextRequest, | |
| { params }: { params: { path: string[] } }, | |
| ) { | |
| console.log("[Proxy Route] params ", params); | |
| if (req.method === "OPTIONS") { | |
| return NextResponse.json({ body: "OK" }, { status: 200 }); | |
| } | |
| const serverConfig = getServerSideConfig(); | |
| // remove path params from searchParams | |
| req.nextUrl.searchParams.delete("path"); | |
| req.nextUrl.searchParams.delete("provider"); | |
| const subpath = params.path.join("/"); | |
| const fetchUrl = `${req.headers.get( | |
| "x-base-url", | |
| )}/${subpath}?${req.nextUrl.searchParams.toString()}`; | |
| const skipHeaders = ["connection", "host", "origin", "referer", "cookie"]; | |
| const headers = new Headers( | |
| Array.from(req.headers.entries()).filter((item) => { | |
| if ( | |
| item[0].indexOf("x-") > -1 || | |
| item[0].indexOf("sec-") > -1 || | |
| skipHeaders.includes(item[0]) | |
| ) { | |
| return false; | |
| } | |
| return true; | |
| }), | |
| ); | |
| // if dalle3 use openai api key | |
| const baseUrl = req.headers.get("x-base-url"); | |
| if (baseUrl?.includes("api.openai.com")) { | |
| if (!serverConfig.apiKey) { | |
| return NextResponse.json( | |
| { error: "OpenAI API key not configured" }, | |
| { status: 500 }, | |
| ); | |
| } | |
| headers.set("Authorization", `Bearer ${serverConfig.apiKey}`); | |
| } | |
| const controller = new AbortController(); | |
| const fetchOptions: RequestInit = { | |
| headers, | |
| method: req.method, | |
| body: req.body, | |
| // to fix #2485: https://stackoverflow.com/questions/55920957/cloudflare-worker-typeerror-one-time-use-body | |
| redirect: "manual", | |
| // @ts-ignore | |
| duplex: "half", | |
| signal: controller.signal, | |
| }; | |
| const timeoutId = setTimeout( | |
| () => { | |
| controller.abort(); | |
| }, | |
| 10 * 60 * 1000, | |
| ); | |
| try { | |
| const res = await fetch(fetchUrl, fetchOptions); | |
| // to prevent browser prompt for credentials | |
| const newHeaders = new Headers(res.headers); | |
| newHeaders.delete("www-authenticate"); | |
| // to disable nginx buffering | |
| newHeaders.set("X-Accel-Buffering", "no"); | |
| // The latest version of the OpenAI API forced the content-encoding to be "br" in json response | |
| // So if the streaming is disabled, we need to remove the content-encoding header | |
| // Because Vercel uses gzip to compress the response, if we don't remove the content-encoding header | |
| // The browser will try to decode the response with brotli and fail | |
| newHeaders.delete("content-encoding"); | |
| return new Response(res.body, { | |
| status: res.status, | |
| statusText: res.statusText, | |
| headers: newHeaders, | |
| }); | |
| } finally { | |
| clearTimeout(timeoutId); | |
| } | |
| } | |