repo_description: ✨ Light and Fast AI Assistant. Support: Web | iOS | MacOS | Android |  Linux | Windows
repo_topics: calclaude chatgpt claude cross-platform desktop fe gemini gemini-pro gemini-server gemini-ultra gpt-4o groq nextjs ollama react tauri tauri-app vercel webui
code: 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);
    }
  }
  