Fastapi Middleware
Middleware is a function that executes before and after each request reaches the route handler.
Middleware can be used to add logging, modify request/response, handle CORS, and other common logic.
* * *
## How Middleware Works
Middleware execution flow:
* Request arrives at middleware
* Middleware executes preprocessing logic
* Middleware passes request to the next middleware or route function
* Route function returns response
* Middleware executes postprocessing logic
* Response is returned to client
!(#)
| Name | Function |
| --- | --- |
| Client | Browser, frontend App, Postman, etc. that initiate HTTP requests to FastAPI |
| Request | HTTP request object containing URL, Header, Body, Cookie and other data |
| Middleware 1 | First layer of processing after request enters |
| Middleware 2 | Second layer of processing logic |
| Middleware N | Multiple middleware executed in sequence |
| Route Handler (Path Operation) | Location where business code is actually executed |
| Response Phase | After route returns Response, the response passes through middleware again |
| Middleware Reverse Return | Response returns in "reverse order" |
| Response | Final data returned to client |
* * *
## Creating Middleware
Use the `@app.middleware("http")` decorator to create middleware:
## Example
```python
import time
from fastapi import FastAPI, Request
app = FastAPI()
@app.middleware("http")
async def add_process_time_header(request: Request, call_next):
# 1. Pre-request processing: record start time
start_time = time.time()
# 2. Pass request to next middleware or route function
response = await call_next(request)
# 3. Post-response processing: calculate processing time and add response header
process_time = time.time() - start_time
response.headers = str(process_time)
return response
@app.get("/")
async def root():
return {"message": "Hello World"}
Code Explanation:
| Part | Description |
| --- | --- |
| `@app.middleware("http")` | Declare this as an HTTP middleware |
| `request: Request` | Current request object |
| `call_next` | Callback to invoke the next middleware or route function |
| `await call_next(request)` | Pass request to the next layer and get response |
> `call_next` receives `request` parameter and returns `response`. You can modify the request before calling `call_next` and modify the response after calling it.
* * *
## Request Logging Middleware
The following middleware logs basic information for each request:
## Example
```python
import time
import logging
from fastapi import FastAPI, Request
app = FastAPI()
logger = logging.getLogger("uvicorn.access")
@app.middleware("http")
async def log_requests(request: Request, call_next):
# Log request information
logger.info(f"Request: {request.method} {request.url}")
start_time = time.time()
response = await call_next(request)
process_time = time.time() - start_time
# Log response information
logger.info(
f"Response: {request.method} {request.url} "
f"status_code={response.status_code} time={process_time:.3f}s"
)
return response
* * *
## Middleware Execution Order
Middleware executes in registration order, requests pass through middleware in forward order, and responses pass through middleware in reverse order:
Request -> MiddlewareA(pre) -> MiddlewareB(pre) -> Route Function Response <- MiddlewareA(post) <- MiddlewareB(post) The registration order of middleware matters. If you have two middleware A and B, and A is registered first, the request passes through A then B, but the response passes through B then A.
* * *
## Using Starlette Built-in Middleware
FastAPI inherits from Starlette and can directly use middleware provided by Starlette:
## Example
```python
from fastapi import FastAPI
from starlette.middleware.httpsredirect import HTTPSRedirectMiddleware
app = FastAPI()
# Force HTTPS redirect
app.add_middleware(HTTPSRedirectMiddleware)
@app.get("/")
async def root():
return {"message": "Access using HTTPS"}
Common built-in middleware:
| Middleware | Description |
| --- | --- |
| `HTTPSRedirectMiddleware` | Force redirect HTTP requests to HTTPS |
| `TrustedHostMiddleware` | Restrict allowed hostnames |
| `GZipMiddleware` | Automatically compress response content |
| `CORSMiddleware` | Handle cross-origin requests (detailed in next chapter) |
* * *
## GZip Compression Middleware
Enabling GZip compression can reduce response size and improve transfer speed:
## Example
```python
from fastapi import FastAPI
from fastapi.middleware.gzip import GZipMiddleware
app = FastAPI()
# Automatically compress when response size exceeds 1000 bytes
app.add_middleware(GZipMiddleware, minimum_size=1000)
@app.get("/")
async def root():
return {"message": "This response may be GZip compressed"}
* * *
## Summary
* Middleware executes common logic in the request/response processing chain
* Use `@app.middleware("http")` to create custom middleware
* `call_next(request)` passes request to the next layer
* Middleware executes in registration order (requests in forward order, responses in reverse order)
* FastAPI/Starlette provides built-in middleware such as CORS, GZip, HTTPS redirect
YouTip