---
title: Middleware
description: Process requests and responses with middleware
---

# Middleware

Middleware processes requests before they reach upstreams and responses before they return to clients.

## Overview

Middleware in Octopus is Rust code that wraps the request/response path. Each
middleware runs in registration order on the way in and reverse order on the way
out:

```
Request → M1 → M2 → M3 → Upstream → M3 → M2 → M1 → Response
```

<Callout type="warn" title="What actually runs today">
  There is **no** `middleware:` configuration array. The global chain is
  assembled in code (`crates/octopus-runtime/src/server.rs`) and contains at most
  two entries: **compression** (when `gateway.compression.enabled`, the default)
  and the **auth gateway** (when auth providers are configured or
  `auth.global_enforce` is on). Compression is registered first, so it is the
  outermost wrapper and compresses the response on the way out. The
  `octopus-middleware` crate ships many more middleware (CORS, rate limiting,
  caching, security headers, WAF, …), but they are **builder-only** — not wired
  to gateway config. Per-route `rate_limit` and `cors` are parsed and stored but
  not enforced in the live chain. See [Middleware reference](/docs/octopus/middleware) for
  the full catalogue and wiring status.
</Callout>

## How Middleware Works

### Execution Order

The chain is built in code, not from config. The live order is:

```text
Request
  → [Compression]        (if gateway.compression.enabled)
    → [Auth gateway]     (if auth_providers non-empty OR auth.global_enforce)
      → Route match → Upstream proxy
    ← Auth gateway (pass-through on the way out)
  ← Compression (compresses the response body)
Response
```

Each middleware is configured through its own config block (`gateway.compression`
and `auth` / `auth_providers`), not through a `middleware:` list.

### Short-Circuiting

Middleware can stop the chain early — for example, the auth gateway returns
`401`/`403` without proxying:

```
Request → Auth gateway (401/403) ──┐
                                    ↓
                                  Response
```

## Built-in Middleware

<Callout type="info">
  Of the middleware below, only **authentication** (via the auth gateway and
  `auth_providers`) and **compression** (via `gateway.compression`) run in the
  live chain today. **Rate limiting** and **CORS** are implemented but
  builder-only — their config is parsed but not enforced at request time. The
  YAML examples here are illustrative; see the linked reference pages for the
  exact, source-verified schema.
</Callout>

### Authentication

```yaml
middleware:
  - auth

auth:
  type: jwt
  secret: ${JWT_SECRET}
  algorithm: HS256
  header: Authorization
  scheme: Bearer
  excluded_paths:
    - "/api/auth/login"
    - "/_/health"
```

See [Authentication Middleware](/docs/octopus/middleware/authentication) for details.

### Rate Limiting

```yaml
middleware:
  - rate_limit

rate_limit:
  strategy: token-bucket
  requests_per_second: 100
  burst: 200
  key_by: ip  # or: user_id, api_key, header
```

See [Rate Limiting Middleware](/docs/octopus/middleware/rate-limiting) for details.

### CORS

```yaml
middleware:
  - cors

cors:
  allowed_origins: ["https://example.com"]
  allowed_methods: [GET, POST, PUT, DELETE]
  allowed_headers: ["Content-Type", "Authorization"]
  exposed_headers: ["X-Request-ID"]
  allow_credentials: true
  max_age: 3600
```

See [CORS Middleware](/docs/octopus/middleware/cors) for details.

### Compression

```yaml
middleware:
  - compression

compression:
  enabled: true
  level: 6
  min_size: 1024
  types:
    - "application/json"
    - "text/html"
```

See [Compression Middleware](/docs/octopus/middleware/compression) for details.

## Custom Middleware

Create custom middleware via plugins:

```rust
use octopus_middleware::prelude::*;

pub struct CustomMiddleware;

#[async_trait]
impl Middleware for CustomMiddleware {
    async fn call(
        &self,
        mut req: Request<Body>,
        next: Next,
    ) -> Result<Response<Body>> {
        // Modify request
        req.headers_mut()
            .insert("X-Custom-Header", "value".parse()?);
        
        // Continue to next middleware
        let mut resp = next.run(req).await?;
        
        // Modify response
        resp.headers_mut()
            .insert("X-Processed-By", "octopus".parse()?);
        
        Ok(resp)
    }
}
```

See [Writing a Plugin](/docs/octopus/plugins/writing-plugins) for details.

## Request Context

Middleware can access and modify request context:

```rust
// Set context value
req.extensions_mut().insert(UserId("123".to_string()));

// Read context value
let user_id = req.extensions().get::<UserId>();
```

## Next Steps

Learn about specific middleware:

- [Middleware reference](/docs/octopus/middleware) - The real chain and full catalogue
- [Authentication](/docs/octopus/middleware/authentication)
- [Rate Limiting](/docs/octopus/middleware/rate-limiting)
- [CORS](/docs/octopus/middleware/cors)
- [Compression](/docs/octopus/middleware/compression)
- [Catalogue](/docs/octopus/middleware/catalogue) - Transformation, caching, and the rest

