# How to Use Middleware with 9Router API Handlers: Implementation Guide

> Learn how to implement middleware with 9Router API handlers. Discover patching source code or using an external reverse-proxy for request interception.

- Repository: [decolua/9router](https://github.com/decolua/9router)
- Tags: how-to-guide
- Published: 2026-05-08

---

**9Router does not expose a public middleware API for its OpenAI-compatible endpoints, so you must either patch the source code in [`src/proxy.js`](https://github.com/decolua/9router/blob/main/src/proxy.js) or place an external reverse-proxy in front of the application to intercept requests.**

9Router is a lightweight routing layer built on Next.js API routes that aggregates AI services behind a unified interface. While it provides a streamlined request pipeline for handling chat, embeddings, and image generation via Server-Sent-Events, the architecture deliberately avoids pluggable Express-style middleware hooks. This guide explains the internal routing mechanism and provides two proven methods for adding custom middleware logic to your 9Router deployment.

## How 9Router Processes HTTP Requests

According to the decolua/9router source code, the HTTP endpoint is built on **Next.js API routes** wired together in [`src/proxy.js`](https://github.com/decolua/9router/blob/main/src/proxy.js). The request pipeline is intentionally minimal: each incoming request is parsed, routed to a specific handler (such as those under `open-sse/handlers/`), and the response is streamed back via Server-Sent-Events.

The central dispatcher in [`src/proxy.js`](https://github.com/decolua/9router/blob/main/src/proxy.js) imports built-in utilities like [`open-sse/utils/requestLogger.js`](https://github.com/decolua/9router/blob/main/open-sse/utils/requestLogger.js) for logging and [`open-sse/utils/streamHelpers.js`](https://github.com/decolua/9router/blob/main/open-sse/utils/streamHelpers.js) for SSE normalization. However, these components are woven into the router at compile time and are not exposed for external extension.

## Why 9Router Lacks a Public Middleware API

Because the routing logic is internal to 9Router, there is **no public hook for adding arbitrary Express-style middleware** (e.g., `app.use(myMiddleware)`). The only "middleware-like" components that exist are the **built-in utilities** that handle cross-cutting concerns like request logging and stream normalization. These are hardcoded into the request flow and cannot be injected dynamically.

If you need custom behavior—such as authentication, request validation, logging, or response transformations—you must implement one of the following workarounds.

## Method 1: Patching the Source Code

The most direct way to use middleware with 9Router API handlers is to modify the source files directly. This approach gives you full control over the request lifecycle but requires maintaining a fork or patch set.

### Injecting Logic into the Central Router

Edit [`src/proxy.js`](https://github.com/decolua/9router/blob/main/src/proxy.js) to insert your own function before the handler is invoked. This is the only way to inject true middleware-style logic that affects all routes.

```javascript
// src/proxy.js – after the imports
import { logRequest } from '@/open-sse/utils/requestLogger';

// … inside the main request handler
export default async function handler(req, res) {
  // Custom middleware – runs before any specific handler
  logRequest(req);               // ← built‑in logger (you can add more)

  // Existing routing logic (unchanged)
  const result = await routeRequest(req);
  sendSseResponse(res, result);
}

```

*Source reference:* [[`src/proxy.js`](https://github.com/decolua/9router/blob/main/src/proxy.js)](https://github.com/decolua/9router/blob/master/src/proxy.js)

### Modifying Individual Handlers

For route-specific middleware, patch the individual handler files. For example, to add API key validation to the chat endpoint:

```javascript
// src/open-sse/handlers/chatCore/streamingHandler.js
export async function streamingHandler(req, res) {
  // ---- Your middleware logic ----
  if (!req.headers['x-api-key'] || req.headers['x-api-key'] !== process.env.MY_API_KEY) {
    res.status(401).json({ error: 'Invalid API key' });
    return;
  }

  // Continue with the original streaming logic
  const stream = await createChatStream(req.body);
  streamToSse(res, stream);
}

```

*Source reference:* [[`open-sse/handlers/chatCore/streamingHandler.js`](https://github.com/decolua/9router/blob/main/open-sse/handlers/chatCore/streamingHandler.js)](https://github.com/decolua/9router/blob/master/open-sse/handlers/chatCore/streamingHandler.js)

## Method 2: External Reverse-Proxy Layer

If you prefer not to modify the 9Router source code, run 9Router behind your own reverse-proxy (NGINX, Cloudflare Workers, etc.) and apply middleware there. The proxy will see the raw HTTP request before it reaches 9Router, allowing you to add headers, rate-limit, or modify the payload.

```nginx

# nginx.conf – place in front of 9Router

server {
  listen 80;
  location /v1/ {
    # Example middleware: add a static header

    add_header X-Custom-Middleware "enabled";

    # Forward to the 9Router instance

    proxy_pass http://127.0.0.1:20128;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
  }
}

```

This approach keeps the 9Router code untouched while giving you full control over HTTP processing.

## Understanding Built-in Middleware-Like Components

While you cannot extend them directly, understanding the existing utilities helps when patching:

- **[`open-sse/utils/requestLogger.js`](https://github.com/decolua/9router/blob/main/open-sse/utils/requestLogger.js)**: Logs every incoming request. You can replicate or extend this pattern when adding custom logging middleware.
- **[`open-sse/utils/streamHelpers.js`](https://github.com/decolua/9router/blob/main/open-sse/utils/streamHelpers.js)**: Normalizes Server-Sent-Event streams, acting like response middleware for SSE formatting.

These files demonstrate the expected patterns for request and response manipulation within the 9Router architecture.

## Summary

- **9Router does not provide a pluggable middleware API** for its OpenAI-compatible endpoints; the routing pipeline is internal and minimal.
- **Patch [`src/proxy.js`](https://github.com/decolua/9router/blob/main/src/proxy.js)** to inject global middleware that runs before any handler executes.
- **Modify individual handlers** (e.g., [`streamingHandler.js`](https://github.com/decolua/9router/blob/main/streamingHandler.js)) for route-specific logic like authentication or validation.
- **Use an external reverse-proxy** (NGINX, etc.) to add middleware without touching the source code.
- **Built-in utilities** like [`requestLogger.js`](https://github.com/decolua/9router/blob/main/requestLogger.js) show the patterns used for cross-cutting concerns but are not externally extensible.

## Frequently Asked Questions

### Does 9Router support Express-style middleware?

No. 9Router is built on Next.js API routes rather than Express, and the [`src/proxy.js`](https://github.com/decolua/9router/blob/main/src/proxy.js) router does not expose an `app.use()` interface or similar hook for adding arbitrary middleware functions. The request pipeline is closed and optimized for SSE streaming.

### Can I add authentication middleware to 9Router?

Yes, but you must implement it via source modification or an external proxy. To add authentication directly, patch [`src/proxy.js`](https://github.com/decolua/9router/blob/main/src/proxy.js) for global checks or modify specific handlers like [`open-sse/handlers/chatCore/streamingHandler.js`](https://github.com/decolua/9router/blob/main/open-sse/handlers/chatCore/streamingHandler.js) to validate headers (e.g., `x-api-key`) before processing the request.

### Where is the request routing logic located in 9Router?

The central routing logic resides in [`src/proxy.js`](https://github.com/decolua/9router/blob/main/src/proxy.js), which dispatches all `/v1/*` requests to the appropriate handler based on the endpoint. This file is the primary integration point if you are patching the source to add middleware.

### Is there a plugin system for 9Router?

No, 9Router does not implement a plugin architecture. The only extension points are the source files themselves ([`src/proxy.js`](https://github.com/decolua/9router/blob/main/src/proxy.js) and the handler modules under `open-sse/handlers/`) or the HTTP layer via a reverse-proxy.