Middleware basics

Middleware wraps every request. It runs in a specific order, and the order matters. Security headers should run on every response. CORS should run early enough to see preflights. Request-ID should run before everything else so logs downstream have context.

Middleware order

Outermost is added last. Inner middleware sees the request first on the way in, last on the way out.

main.py
python
from starlette.middleware.base import BaseHTTPMiddleware
from starlette.requests import Request

class SecurityHeadersMiddleware(BaseHTTPMiddleware):
    """Attach a minimal set of security headers to every response."""

    async def dispatch(self, request: Request, call_next):
        response = await call_next(request)
        response.headers.setdefault("X-Content-Type-Options", "nosniff")
        response.headers.setdefault("X-Frame-Options", "DENY")
        response.headers.setdefault("Referrer-Policy", "no-referrer")
        return response

app.add_middleware(SecurityHeadersMiddleware)

Three headers that cost nothing and block a family of attacks. nosniff stops MIME confusion. DENY forbids framing the page. no-referrer keeps the Referer header empty on outbound links from your responses.

Quiz: Quiz

Loading practice…