Middleware
Fenrir supports two types of middleware: request/response middleware (decorators) and ASGI middleware classes (wrapping the entire ASGI app).
Request/Response Middleware
before_request
Executes before the request handler. Can modify the request or abort early.
1 2 3 4 5 | |
after_request
Executes after the request handler. Can modify the response before sending.
1 2 3 4 5 | |
teardown_request
Executes after the response is sent. Used for cleanup regardless of success or failure.
1 2 3 | |
Combining Middleware
1 2 3 4 5 6 7 8 9 10 11 12 | |
Authentication Middleware
1 2 3 4 5 6 7 8 | |
ASGI Middleware Classes
ASGI middleware wraps the entire application. They are added using app.add_middleware().
1 2 3 4 5 | |
Middleware is stacked in addition order — the first middleware added becomes the outermost layer (executes first on requests, last on responses).
1 2 3 4 5 | |
CORSMiddleware
Full CORS support for HTTP and WebSocket requests. Handles preflight OPTIONS requests automatically.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | |
Parameters:
allow_origins: List of allowed origins, or"*"for all (default:"*")allow_methods: List of allowed HTTP methods (default:"*")allow_headers: List of allowed headers (default:"*")allow_credentials: Whether to allow credentials (default:False)expose_headers: Headers to expose to the browser (default:"")max_age: Max age for preflight cache in seconds (default:600)
WebSocket CORS: The middleware also handles CORS for WebSocket upgrade requests by checking the Origin header against allowed origins.
GZipMiddleware
Automatic gzip compression for responses above a configurable size threshold. Uses streaming compression for memory efficiency on large responses.
1 2 3 | |
Parameters:
minimum_size: Minimum response size in bytes to compress (default:500)compresslevel: Gzip compression level 1-9 (default:6)
Compressible types: The middleware only compresses responses with these content types:
text/plain,text/html,text/css,text/xml,text/javascriptapplication/json,application/javascript,application/xmlapplication/rss+xml,application/atom+xml,application/vnd.ms-fontobjectfont/opentype,image/svg+xml,application/xhtml+xml,application/wasm- Any
text/*content type
Responses with status codes 204 or 304 are never compressed.
RequestIDMiddleware
Auto-generates unique request IDs or forwards client-provided IDs.
1 2 3 4 5 6 7 8 9 10 11 12 13 | |
Parameters:
header_name: Header name for the request ID (default:"X-Request-ID")generator: Custom ID generator function (default:uuid.uuid4)
If the client sends a request ID header, it is forwarded as-is. Otherwise, the generator is called to create a new ID.
RateLimitMiddleware
Sliding-window rate limiter per client IP or per custom key. Returns HTTP 429 with a JSON body and Retry-After header when exceeded.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | |
Parameters:
max_requests: Maximum requests per window (default:100)window_seconds: Time window in seconds (default:60)key_func: Custom function to extract client key (default: client IP)retry_after_header: Include Retry-After header in 429 responses (default:True)redis_client: Redis async client for distributed rate limiting (default:None, uses in-memory)
Default key extraction: Checks X-Forwarded-For header first, then falls back to the client IP from scope["client"].
Algorithm: Uses a sliding window that tracks timestamps of requests. Automatically cleans up expired entries periodically.
BodyLimitMiddleware
Rejects requests exceeding a maximum body size, preventing DoS via large payloads. Monitors chunk size for unknown-length (chunked) bodies.
1 2 3 4 5 6 7 | |
Parameters:
max_content_length: Maximum allowed body size in bytes (default:10_485_760— 10 MB)status_code: HTTP status code returned when body exceeds limit (default:413)
Chunk monitoring: For requests without a Content-Length header (chunked transfer), the middleware wraps receive() to monitor the actual body size and rejects if the limit is exceeded.
CSRFMiddleware
Enforces CSRF token validation for state-changing methods (POST, PUT, DELETE, PATCH). Safe methods (GET, HEAD, OPTIONS) are always allowed.
1 2 3 | |
When auto_generate=True (default), a CSRF token cookie is injected into every safe-method response. The client must read this cookie and send it back in the X-CSRF-Token header for subsequent state-changing requests.
Parameters:
secret_key: Secret key for token generation (default:"")cookie_name: Name of the CSRF cookie (default:"_csrf_token")header_name: Header name for the CSRF token (default:"X-CSRF-Token")safe_methods: Set of methods that bypass CSRF validation (default:frozenset({"GET", "HEAD", "OPTIONS"}))auto_generate: Auto-inject CSRF cookie on safe methods (default:True)
Token generation: Uses HMAC-SHA256 with the secret key and current timestamp. Falls back to secrets.token_hex(32) if no secret key is provided.
Middleware Execution Order
ASGI middleware stacks in addition order. The first middleware added is the outermost layer:
1 2 3 4 5 6 7 | |
Recommended order:
- CORSMiddleware — Handle CORS preflight before anything else
- BodyLimitMiddleware — Reject oversized payloads early
- RateLimitMiddleware — Rate limit before expensive processing
- GZipMiddleware — Compress after rate limiting to avoid compressing 429 responses
- RequestIDMiddleware — Add request ID for tracing
- CSRFMiddleware — Validate CSRF tokens for state-changing requests