How API Routes in NextChat Function as Proxies for AI Services

NextChat implements every external AI provider as a stateless Next.js API route that authenticates requests, forwards them to the vendor endpoint, and streams the response back to the client while sanitizing headers and enforcing timeouts.

The ChatGPTNextWeb/NextChat repository uses a unified proxy architecture to decouple the frontend from AI vendor specifics. Each provider—OpenAI, Azure OpenAI, Anthropic, X‑AI, or custom endpoints—is exposed through a dedicated route in app/api/ that handles authentication, request forwarding, and response streaming without persisting state.

The Three-Step Proxy Pattern

Every AI service proxy in NextChat follows an identical three-phase pipeline implemented across app/api/openai.ts, app/api/azure.ts, and related files.

Step 1: Request Handling and Validation

The route receives a standard NextRequest and immediately validates access. An authentication helper imported from app/api/auth.ts checks the bearer token against the expected ModelProvider (e.g., ModelProvider.GPT). The route also validates that the requested sub‑path exists within an allowed whitelist such as ALLOWED_PATH or ALLOWD_PATH. For OPTIONS requests, the route returns an immediate CORS pre‑flight response.

Step 2: Target URL Construction and Forwarding

The proxy constructs the final destination URL by combining a base URL from getServerSideConfig() or an x‑base‑url request header with the path parameters (params.path). It initializes an AbortController to enforce a hard 10‑minute timeout on all upstream requests. The code creates a sanitized Headers collection that drops potentially problematic fields like connection, host, and origin, then injects the provider‑specific authentication header (e.g., Authorization: Bearer … or x‑api‑key). The request body is forwarded unchanged, though OpenAI routes may re‑read it once to apply model‑filtering logic.

Step 3: Response Sanitization and Streaming

After executing fetch against the constructed URL, the proxy sanitizes response headers to prevent browser credential dialogs and buffering conflicts. It explicitly removes www‑authenticate, strips content‑encoding to avoid Brotli‑gzip issues, and adds X‑Accel‑Buffering: no to ensure streaming works correctly through reverse proxies. For OpenAI‑specific routes, the OpenAI‑Organization header is stripped when not configured. Finally, the route returns a new Response object that pipes the provider’s body stream directly to the client.

Provider-Specific Implementation Details

While the core pattern is shared, each AI vendor requires minor adaptations in its dedicated route file.

OpenAI and Azure OpenAI

Both providers utilize the shared requestOpenai helper defined in app/api/common.ts (lines 46‑84). This helper detects Azure deployments by checking for the /azure/deployments path pattern and automatically rewrites the query string to include the required api‑version parameter. The OpenAI route (app/api/openai.ts, lines 29‑44) additionally validates paths against the OpenaiPath whitelist and filters out disallowed GPT‑4 models using serverConfig.customModels.

Anthropic and X‑AI

The Anthropic route (app/api/anthropic.ts) builds its own request logic because the provider expects the x‑api‑key header (or Authorization) alongside a mandatory anthropic‑version header. It also injects the anthropic‑dangerous‑direct‑browser‑access flag required by Anthropic’s API. The X‑AI route (app/api/xai.ts) follows a similar pattern but uses only the Authorization header and validates against ServiceProvider.XAI.

Generic Proxy via x-base-url

For third‑party or self‑hosted models, app/api/proxy.ts provides a universal forwarding mechanism. This route reads the x‑base‑url header from the client to determine the upstream endpoint, allowing any compatible service to be reached without a dedicated code path. It applies the same timeout and header hygiene logic as the provider‑specific routes.

Security and Performance Controls

NextChat’s proxy layer enforces several critical safeguards across all routes.

Header Hygiene. The proxy explicitly removes headers that could trigger browser authentication dialogs or leak internal infrastructure details. Dropped headers include connection, host, origin, and www‑authenticate.

Timeout Protection. Every upstream request is wrapped in an AbortController that triggers after 10 minutes, preventing hung connections from consuming server resources indefinitely.

Model Filtering. Server‑side configuration via serverConfig.customModels allows administrators to define a whitelist of permitted models. The OpenAI route inspects the request body and rejects calls to models not present in this list before they reach the external API.

Code Examples

Calling the OpenAI Proxy from the Client

await fetch('/api/openai/v1/chat/completions', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    Authorization: 'Bearer <your-next-chat-token>',
  },
  body: JSON.stringify({
    model: 'gpt-4o-mini',
    messages: [{ role: 'user', content: 'Hello!' }],
  }),
});

This request hits app/api/openai.ts, passes authentication, and is forwarded to the OpenAI endpoint defined in SERVER_CONFIG.baseUrl. The streaming response returns unchanged to the browser.

Using the Generic Proxy for Custom Services

await fetch('/api/proxy/custom-service/v1/predict', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'x-base-url': 'https://api.customai.com',
    Authorization: 'Bearer <your-token>',
  },
  body: JSON.stringify({ prompt: 'Explain quantum entanglement' }),
});

app/api/proxy.ts extracts x-base-url, constructs https://api.customai.com/custom-service/v1/predict, forwards the request, and streams the response back.

Server-Side Helper Usage

import { requestOpenai } from '@/app/api/common';

export async function callChatCompletion(req: NextRequest) {
  // requestOpenai handles auth headers, timeouts, and sanitization
  const response = await requestOpenai(req);
  return response; // streamed back to the client
}

The requestOpenai helper abstracts the forwarding logic for OpenAI‑compatible services, including Azure OpenAI detection.

Summary

  • NextChat implements AI providers as stateless Next.js API routes that authenticate, forward, and stream requests without persisting data.
  • The three-step pattern (validation, forwarding, sanitization) is shared across app/api/openai.ts, app/api/azure.ts, app/api/anthropic.ts, and app/api/xai.ts.
  • Header hygiene and 10‑minute timeouts protect against browser credential leaks and resource exhaustion.
  • Model filtering via serverConfig.customModels blocks disallowed models at the proxy layer.
  • The generic proxy in app/api/proxy.ts enables integration with any OpenAI‑compatible endpoint using the x‑base‑url header.

Frequently Asked Questions

How does NextChat handle authentication for AI providers?

Each route invokes the auth helper from app/api/auth.ts to validate the bearer token and expected ModelProvider. After validation, the proxy injects the provider‑specific secret (API key) into the request headers—using Authorization: Bearer for OpenAI/X‑AI or x‑api‑key for Anthropic—before forwarding to the upstream service.

What is the purpose of the generic proxy route in NextChat?

The app/api/proxy.ts route allows users to connect to any third‑party or self‑hosted AI service without modifying the codebase. By accepting an x‑base‑url header from the client, it constructs the target URL dynamically and applies the same timeout, header sanitization, and streaming logic used by native provider routes.

How does NextChat prevent unauthorized access to specific AI models?

Before forwarding to OpenAI, the route inspects the request body for the model field and compares it against serverConfig.customModels. If the requested model is not in the whitelist, the proxy rejects the request immediately, ensuring expensive or restricted models cannot be accessed even if the user possesses a valid API token.

Why does NextChat strip certain headers like www-authenticate?

The proxy removes headers such as www‑authenticate, connection, host, and origin to prevent browsers from displaying credential dialogs and to avoid leaking internal server details. It also strips content‑encoding to prevent Brotli or gzip conflicts during streaming, ensuring compatible behavior across different deployment environments and reverse proxies.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →