docs/en/docs/tutorial/middleware.md
You can add middleware to FastAPI applications.
A "middleware" is a function that works with every request before it is processed by any specific path operation. And also with every response before returning it.
/// note | Technical Details
If you have dependencies with yield, the exit code will run after the middleware.
If there were any background tasks (covered in the Background Tasks section, you will see it later), they will run after all the middleware.
///
To create a middleware you use the decorator @app.middleware("http") on top of a function.
The middleware function receives:
request.call_next that will receive the request as a parameter.
request to the corresponding path operation.response generated by the corresponding path operation.response before returning it.{* ../../docs_src/middleware/tutorial001_py310.py hl[8:9,11,14] *}
/// tip
Keep in mind that custom proprietary headers can be added using the X- prefix.
But if you have custom headers that you want a client in a browser to be able to see, you need to add them to your CORS configurations (CORS (Cross-Origin Resource Sharing)) using the parameter expose_headers documented in Starlette's CORS docs.
///
/// note | Technical Details
You could also use from starlette.requests import Request.
FastAPI provides it as a convenience for you, the developer. But it comes directly from Starlette.
///
response { #before-and-after-the-response }You can add code to be run with the request, before any path operation receives it.
And also after the response is generated, before returning it.
For example, you could add a custom header X-Process-Time containing the time in seconds that it took to process the request and generate a response:
{* ../../docs_src/middleware/tutorial001_py310.py hl[10,12:13] *}
/// tip
Here we use time.perf_counter() instead of time.time() because it can be more precise for these use cases. 🤓
///
When you add multiple middlewares using either @app.middleware() decorator or app.add_middleware() method, each new middleware wraps the application, forming a stack. The last middleware added is the outermost, and the first is the innermost.
On the request path, the outermost middleware runs first.
On the response path, it runs last.
For example:
app.add_middleware(MiddlewareA)
app.add_middleware(MiddlewareB)
This results in the following execution order:
Request: MiddlewareB → MiddlewareA → route
Response: route → MiddlewareA → MiddlewareB
This stacking behavior ensures that middlewares are executed in a predictable and controllable order.
You can later read more about other middlewares in the Advanced User Guide: Advanced Middleware.
You will read about how to handle <abbr title="Cross-Origin Resource Sharing">CORS</abbr> with a middleware in the next section.