How OmniRoute Validates Incoming API Requests: A Complete Layered Security Guide

OmniRoute performs multi-layer validation on incoming requests, combining CORS guards, Content-Type enforcement, byte-size admission controls, Zod schema validation, model availability checks, prompt-injection detection, and structural admission before any request reaches downstream providers.

OmniRoute operates as a unified routing layer for multiple AI providers, making robust request validation essential for security, performance, and API consistency. The validation pipeline is deliberately layered—each stage filters out invalid or harmful traffic before expensive processing begins. This article examines the complete validation flow as implemented in diegosouzapw/OmniRoute, with specific file paths and code examples from the v3.8.51 release.

Pre-Flight and Protocol Validation

CORS and HTTP Method Enforcement

Every request first encounters the CORS and HTTP method guard in src/app/api/v1/chat/completions/route.ts. The OPTIONS function handles pre-flight requests and injects required Access-Control-Allow-Origin headers.

This layer prevents unwanted cross-origin calls and ensures clients use the correct HTTP verb before any payload processing occurs.

Content-Type Strictness

OmniRoute rejects any request lacking the application/json Content-Type header. In src/app/api/v1/chat/completions/route.ts (lines 94–100), mismatched headers trigger an immediate 415 Unsupported Media Type response.

This mirrors OpenAI and Anthropic API behavior, ensuring bodies are parsed as JSON only.

// Valid request header
headers: {
  "Content-Type": "application/json",  // ✅ Required
}

# Rejected request example

curl -X POST http://localhost:20128/v1/chat/completions \
     -H "Content-Type: text/plain" \
     -d '{"model":"openai/gpt-4","messages":[]}'

# → 415 Unsupported Media Type

Resource Protection and Admission Control

Byte-Size Admission with Chat Admission Flow

Before parsing any body, OmniRoute enforces a hard byte limit through the admitChatRequest function in src/app/api/v1/chat/completions/route.ts (lines 12–20). This reserves capacity and prevents oversized payloads from causing OOM crashes or resource exhaustion.

The admission logic lives in src/shared/middleware/chatBodyAdmission.ts, which handles capacity tracking and size enforcement.

One-Time JSON Parsing

The request body is parsed exactly once via await request.json() at lines 44–46 of the completions route. Failed parsing immediately invalidates the request.

This guarantees a single source of truth for the body object and eliminates double-parsing overhead.

Schema and Semantic Validation

Top-Level Shape Guard with Zod

OmniRoute applies a permissive Zod schema that performs rapid structural validation:

  • Parsed body must be an object
  • model is optional and nullable (string)
  • messages is optional (array)

Located at lines 77–82 of src/app/api/v1/chat/completions/route.ts, this schema uses .passthrough() mode—extra fields flow downstream untouched. The safeParse call at line 52 quickly weeds out non-object payloads (e.g., raw strings) without rejecting valid extensions.

// Zod shape guard (simplified)
const bodySchema = z.object({
  model: z.string().nullable().optional(),
  messages: z.array(z.any()).optional(),
}).passthrough();

Model Availability and Retirement Guards

Two distinct checks verify model viability:

  • assertCommonChatGptWebModelAvailable (lines 62–73): Validates against retired web-facing models
  • assertRuntimeModelProviderAvailable (lines 91–98): Confirms the runtime provider still supports the requested model

If a model is deprecated, the system returns a provider-specific 400 or 404 error with structured details like { type: "provider_error", code: "MODEL_RETIRING" }.

// Example: Retired model rejection
await fetch("/v1/chat/completions", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ 
    model: "openai/old-model",  // ❌ Retired
    messages: [] 
  }),
});
// → 400 with provider error code

Prompt-Injection Detection

The Injection Guard middleware—instantiated at line 42 as injectionGuard and invoked inside handleChat—scans request bodies for malicious prompt patterns before any provider forwarding.

This security layer in src/middleware/promptInjectionGuard.ts blocks attempts to manipulate system behavior through carefully crafted inputs.

Structural Admission with Full Chat Schema

After passing the shape guard, payloads undergo admitChatStructure validation (lines 76–86). This applies the complete chat schema defined in src/sse/handlers/chat.ts, verifying:

  • Message object structure and valid roles
  • Token limit compliance
  • Tool call formatting
  • Stream parameter validity

Only fully validated requests proceed to handleChat for provider dispatch.

Cross-Endpoint Validation Standards

Global Zod Schemas

Routes beyond chat completions import shared schemas from src/shared/validation/schemas/*.ts:

Schema File Purpose
src/shared/validation/schemas/apiV1.ts Pagination parameters, generic API IDs, limit specifications
src/shared/validation/schemas/provider.ts Provider IDs, model lists, provider-specific constraints

These files provide a single source of truth for request contracts across the entire router surface.

Route-Specific Guardrails

Individual endpoints add tailored validation layers:

  • src/app/api/v1/audio/speech/route.ts: Validates audio MIME types for synthesis requests
  • src/app/api/v1/files/[id]/content/route.ts: Validates Range header formatting for partial content retrieval

Each route contains lightweight, semantic-appropriate guards that reduce bug surface area without duplicating global logic.

Complete Validation Flow Overview

A typical chat request traverses this pipeline:

  1. CORS pre-flight via OPTIONS handler
  2. Content-Type check (reject non-JSON with 415)
  3. Byte-size admission and capacity reservation
  4. Single JSON parse with failure handling
  5. Top-level Zod shape guard (permissive, passthrough)
  6. Model retirement guard (web-model availability)
  7. Runtime provider availability check
  8. Prompt-injection detection
  9. Structural admission (full chat schema validation)
  10. Dispatch to handleChat for provider execution

Each layer fails fast with specific status codes and error messages, enabling precise client-side troubleshooting.

Summary

  • Protocol validation (CORS, Content-Type, HTTP methods) filters malformed traffic immediately in src/app/api/v1/chat/completions/route.ts
  • Resource protection via admitChatRequest enforces byte limits and capacity reservation before body parsing
  • Zod schema validation operates in two phases: permissive shape guard first, full structural admission second
  • Security middleware including injectionGuard and model availability checks prevents malicious or obsolete requests from reaching providers
  • Shared schema files in src/shared/validation/schemas/ maintain API consistency across all endpoints
  • Route-specific guards add semantic validation tailored to individual endpoint requirements

Frequently Asked Questions

What happens if I send the wrong Content-Type header?

OmniRoute returns 415 Unsupported Media Type immediately. The check at lines 94–100 of src/app/api/v1/chat/completions/route.ts enforces strict application/json requirements to match OpenAI/Anthropic API behavior and ensure safe body parsing.

How does OmniRoute prevent oversized request bodies from crashing the server?

The Chat Admission flow in src/shared/middleware/chatBodyAdmission.ts enforces hard byte limits and reserves capacity before any JSON parsing occurs. This prevents memory exhaustion from malicious or accidental large payloads.

Can additional fields be included in the request body beyond the documented parameters?

Yes. The top-level Zod schema uses .passthrough() mode, allowing extra fields to flow downstream unchanged. Only the core structure (object type, optional model string, optional messages array) is validated at the initial layer.

What error code is returned for retired or unsupported models?

The system returns 400 Bad Request with a structured error object containing type: "provider_error" and code: "MODEL_RETIRING" or similar provider-specific codes. This occurs after the assertCommonChatGptWebModelAvailable or assertRuntimeModelProviderAvailable checks fail.

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 →