# How API Routes in NextChat Function as Proxies for AI Services

> Discover how NextChat API routes act as secure proxies for AI services. Learn about request authentication, vendor forwarding, and response streaming for a seamless AI experience.

- Repository: [NextChat/NextChat](https://github.com/ChatGPTNextWeb/NextChat)
- Tags: internals
- Published: 2026-02-28

---

**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`](https://github.com/ChatGPTNextWeb/NextChat/blob/main/app/api/openai.ts), [`app/api/azure.ts`](https://github.com/ChatGPTNextWeb/NextChat/blob/main/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`](https://github.com/ChatGPTNextWeb/NextChat/blob/main/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`](https://github.com/ChatGPTNextWeb/NextChat/blob/main/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`](https://github.com/ChatGPTNextWeb/NextChat/blob/main/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`](https://github.com/ChatGPTNextWeb/NextChat/blob/main/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`](https://github.com/ChatGPTNextWeb/NextChat/blob/main/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`](https://github.com/ChatGPTNextWeb/NextChat/blob/main/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

```typescript
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`](https://github.com/ChatGPTNextWeb/NextChat/blob/main/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

```typescript
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`](https://github.com/ChatGPTNextWeb/NextChat/blob/main/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

```typescript
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`](https://github.com/ChatGPTNextWeb/NextChat/blob/main/app/api/openai.ts), [`app/api/azure.ts`](https://github.com/ChatGPTNextWeb/NextChat/blob/main/app/api/azure.ts), [`app/api/anthropic.ts`](https://github.com/ChatGPTNextWeb/NextChat/blob/main/app/api/anthropic.ts), and [`app/api/xai.ts`](https://github.com/ChatGPTNextWeb/NextChat/blob/main/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`](https://github.com/ChatGPTNextWeb/NextChat/blob/main/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`](https://github.com/ChatGPTNextWeb/NextChat/blob/main/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`](https://github.com/ChatGPTNextWeb/NextChat/blob/main/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.