Quick Start
How It Works
Middleware executes in an onion model: each middleware wraps the next, with the handler at the center.- Inspect/modify the request before calling
call_next - Inspect/modify the response after
call_nextreturns - Short-circuit by returning early without calling
call_next - Reject by raising an exception
Hooks
Override these methods to intercept specific request types:Hook nesting
When you override bothon_request and a specific hook, they nest: on_request wraps the specific hook.
Context
Every hook receives aServerMiddlewareContext with:
Context is immutable. Use
context.copy() to pass data downstream:Examples
- Authentication
- Rate Limiting
- Connection Guard
Reject requests without a valid API key:
Middleware Order
Order matters. Middleware runs in the order added, with earlier middleware wrapping later ones.Best Practices
- Single responsibility: Each middleware does one thing
- Fail fast: Reject invalid requests early, before expensive operations
- Always call
call_next: Unless intentionally short-circuiting - Re-raise exceptions: If you catch errors to log them, always re-raise
Full Example
middleware_example.py
Complete working server with logging, auth, rate limiting, and validation middleware.