mirror of https://github.com/tiangolo/fastapi.git
96 lines
4.1 KiB
Markdown
96 lines
4.1 KiB
Markdown
# Middleware { #middleware }
|
|
|
|
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.
|
|
|
|
* It takes each **request** that comes to your application.
|
|
* It can then do something to that **request** or run any needed code.
|
|
* Then it passes the **request** to be processed by the rest of the application (by some *path operation*).
|
|
* It then takes the **response** generated by the application (by some *path operation*).
|
|
* It can do something to that **response** or run any needed code.
|
|
* Then it returns the **response**.
|
|
|
|
/// 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](background-tasks.md){.internal-link target=_blank} section, you will see it later), they will run *after* all the middleware.
|
|
|
|
///
|
|
|
|
## Create a middleware { #create-a-middleware }
|
|
|
|
To create a middleware you use the decorator `@app.middleware("http")` on top of a function.
|
|
|
|
The middleware function receives:
|
|
|
|
* The `request`.
|
|
* A function `call_next` that will receive the `request` as a parameter.
|
|
* This function will pass the `request` to the corresponding *path operation*.
|
|
* Then it returns the `response` generated by the corresponding *path operation*.
|
|
* You can then further modify the `response` before returning it.
|
|
|
|
{* ../../docs_src/middleware/tutorial001_py39.py hl[8:9,11,14] *}
|
|
|
|
/// tip
|
|
|
|
Keep in mind that custom proprietary headers can be added <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers" class="external-link" target="_blank">using the `X-` prefix</a>.
|
|
|
|
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)](cors.md){.internal-link target=_blank}) using the parameter `expose_headers` documented in <a href="https://www.starlette.dev/middleware/#corsmiddleware" class="external-link" target="_blank">Starlette's CORS docs</a>.
|
|
|
|
///
|
|
|
|
/// 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.
|
|
|
|
///
|
|
|
|
### Before and after the `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_py39.py hl[10,12:13] *}
|
|
|
|
/// tip
|
|
|
|
Here we use <a href="https://docs.python.org/3/library/time.html#time.perf_counter" class="external-link" target="_blank">`time.perf_counter()`</a> instead of `time.time()` because it can be more precise for these use cases. 🤓
|
|
|
|
///
|
|
|
|
## Multiple middleware execution order { #multiple-middleware-execution-order }
|
|
|
|
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:
|
|
|
|
```Python
|
|
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.
|
|
|
|
## Other middlewares { #other-middlewares }
|
|
|
|
You can later read more about other middlewares in the [Advanced User Guide: Advanced Middleware](../advanced/middleware.md){.internal-link target=_blank}.
|
|
|
|
You will read about how to handle <abbr title="Cross-Origin Resource Sharing">CORS</abbr> with a middleware in the next section.
|