mirror of
				https://github.com/ChatGPTNextWeb/ChatGPT-Next-Web.git
				synced 2025-11-04 16:23:41 +08:00 
			
		
		
		
	
		
			
				
	
	
		
			90 lines
		
	
	
		
			2.7 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			90 lines
		
	
	
		
			2.7 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
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);
 | 
						|
  }
 | 
						|
}
 |