Backend Development 6 min read

Master FastAPI Middleware: From Built‑in to Custom Auth and Logging

This guide explains how FastAPI middleware works, outlines its request‑response lifecycle, shows built‑in examples like CORS and HTTPS redirect, and demonstrates how to create custom middleware for logging, authentication, and other cross‑cutting concerns.

Code Mala Tang
Code Mala Tang
Code Mala Tang
Master FastAPI Middleware: From Built‑in to Custom Auth and Logging

Middleware is a function that runs before each request is handled by a specific path operation and also runs before each response is returned.

It receives every request sent to the application.

It can operate on the request or run necessary code.

It then passes the request to the rest of the application (handled by a path operation).

It receives the response generated by the application.

It can operate on the response or run necessary code.

Finally, it returns the response.

Overall, middleware execution can be divided into the following stages:

1. Request phase: Middleware processes the request in the order it was added.

2. Routing: The request reaches the corresponding path operation function.

3. Response phase: Middleware processes the response in reverse order.

<code>Request → [Middleware1 → Middleware2 → Route Handler → Middleware2 → Middleware1] → Response</code>

Middleware wraps the application, intercepting all incoming requests and outgoing responses. It executes in the order added (similar to the onion model: request from outer to inner, response from inner to outer).

Typical use cases include:

Global authentication (e.g., JWT verification)

Request logging

Adding custom response headers

Exception handling

Rate limiting or caching

Built‑in Middleware

FastAPI provides several built‑in middleware, such as the CORS middleware:

<code>from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware

app = FastAPI()

app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],  # allowed origins
    allow_methods=["*"],  # allowed HTTP methods
    allow_headers=["*"],  # allowed request headers
)
</code>

HTTPS redirect middleware:

<code>from fastapi.middleware.httpsredirect import HTTPSRedirectMiddleware

app.add_middleware(HTTPSRedirectMiddleware)  # force all requests to use HTTPS
</code>

Creating Middleware

Beyond the built‑ins, you can define custom middleware by decorating a function with @app.middleware("http") .

A middleware function receives the following parameters:

request : the incoming request.

call_next : a function that forwards the request to the appropriate path operation.

The function returns the response generated by that path operation.

You can modify the response before returning it.

<code>import time
from fastapi import FastAPI, Request

app = FastAPI()

@app.middleware("http")
async def add_process_time_header(request: Request, call_next):
    start_time = time.perf_counter()
    response = await call_next(request)
    process_time = time.perf_counter() - start_time
    response.headers["X-Process-Time"] = str(process_time)
    return response
</code>

This adds a custom X-Process-Time header containing the time taken to process the request (in seconds).

Example of a custom authentication middleware:

<code>from fastapi import FastAPI, Request, Response
from starlette.middleware.base import BaseHTTPMiddleware

class AuthMiddleware(BaseHTTPMiddleware):
    async def dispatch(self, request: Request, call_next):
        api_key = request.headers.get("X-API-KEY")
        if api_key != "secret-key":  # replace with your key validation logic
            return Response("Unauthorized", status_code=401)
        response = await call_next(request)
        return response

app.add_middleware(AuthMiddleware)

@app.get("/secure-data")
async def secure_endpoint():
    return {"message": "You accessed protected data!"}
</code>

The middleware checks the X-API-KEY header.

If the key is missing or incorrect, it returns a 401 Unauthorized response.

Precautions

Avoid performing time‑consuming operations (e.g., synchronous blocking code) inside middleware.

Exceptions raised in middleware are returned directly to the client and are not caught by FastAPI’s exception handlers unless you handle them manually.

Middleware cannot directly use FastAPI’s dependency‑injection system.

Summary

By flexibly using middleware, you can add global functionality to a FastAPI application without repeating code in each route. For more details, refer to the official FastAPI documentation.

backendPythonmiddlewareloggingAuthenticationfastapi
Code Mala Tang
Written by

Code Mala Tang

Read source code together, write articles together, and enjoy spicy hot pot together.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.