tezvyn:

Custom FastAPI Middleware: The BaseHTTPMiddleware Helper

AI-drafted, machine-checkedSource: fastapi.tiangolo.comintermediate

FastAPI's BaseHTTPMiddleware lets you wrap endpoints to run code before and after they execute. Use it to add custom headers or log request times. The footgun: reading `request.body()` in the middleware will break the endpoint, as the body can only be read…

WHY IT EXISTS: FastAPI applications often need to perform the same action on many or all incoming requests, like verifying a token or adding a specific header to every response. Writing this logic in every single endpoint is repetitive and error-prone. Middleware solves this by centralizing this "cross-cutting" logic.

THE MENTAL MODEL: BaseHTTPMiddleware acts like a checkpoint in your application's request/response cycle. An incoming request stops at the middleware, which can inspect it. It then passes the request down the line using a function called call_next. When the endpoint is done and a response is coming back up, it passes through the middleware again, which can inspect or modify the final response before it's sent to the client.

HOW IT WORKS: You create a class that inherits from Starlette's BaseHTTPMiddleware. The core logic lives in an async def dispatch(self, request, call_next) method. Inside dispatch, code before response = await call_next(request) runs before the endpoint. Code after that line runs after the endpoint has generated a response. You can modify the request before call_next or modify the response object before returning it. The middleware is then added to the FastAPI app instance using app.add_middleware().

WHEN TO USE IT: Use it for simple, synchronous-style async logic that needs to wrap the request/response cycle. Common uses include: calculating and adding an X-Process-Time header, checking for a required X-Token header and returning a 403 error if it's missing, or logging basic request metadata.

WHEN NOT TO USE IT: Avoid BaseHTTPMiddleware if you need to read the request body. This is a common footgun because the body is a stream that can only be read once; consuming it in the middleware leaves nothing for the endpoint. For body inspection, or for cases involving background tasks and streaming responses, writing a pure ASGI middleware is the more robust solution.

ONE CANONICAL EXAMPLE: A common use is adding a custom header to track request processing time. In the dispatch method, you record the start time. Then you await call_next(request). After the response is returned, you calculate the total time, add it to the response headers via response.headers['X-Process-Time'] = str(process_time), and finally return the modified response.

Read the original → fastapi.tiangolo.com

Get five bites like this every day.

Tezvyn delivers a daily feed of 60-second tech bites with quizzes to lock in what you learn.