File size: 4,859 Bytes
a152b95
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
# Middleware in FastAPI

Middleware is a function that processes every request before it reaches a route handler and every response before it is returned to the client. FastAPI supports both ASGI middleware (from Starlette) and its own decorator-based middleware.

## Custom Middleware

Use the `@app.middleware("http")` decorator to create custom middleware:

```python
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"] = f"{process_time:.4f}"
    return response
```

The middleware receives the incoming `Request` object and a `call_next` function. Calling `await call_next(request)` passes the request to the next middleware or route handler in the chain and returns the `Response`. You can modify both the request (before `call_next`) and the response (after `call_next`).

## CORS Middleware

Cross-Origin Resource Sharing (CORS) is configured using `CORSMiddleware` from Starlette:

```python
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware

app = FastAPI()

app.add_middleware(
    CORSMiddleware,
    allow_origins=["https://example.com", "https://app.example.com"],
    allow_credentials=True,
    allow_methods=["GET", "POST", "PUT", "DELETE"],
    allow_headers=["Authorization", "Content-Type"],
    expose_headers=["X-Custom-Header"],
    max_age=600,
)
```

The `CORSMiddleware` parameters:

| Parameter            | Default | Description                                        |
|----------------------|---------|----------------------------------------------------|
| `allow_origins`      | `[]`    | List of allowed origin URLs                        |
| `allow_origin_regex` | `None`  | Regex pattern for matching allowed origins         |
| `allow_methods`      | `["GET"]` | HTTP methods allowed for cross-origin requests  |
| `allow_headers`      | `[]`    | HTTP headers allowed in cross-origin requests      |
| `allow_credentials`  | `False` | Whether cookies are permitted in cross-origin requests |
| `expose_headers`     | `[]`    | Response headers accessible to the browser         |
| `max_age`            | `600`   | Seconds the browser caches preflight results       |

To allow all origins, use `allow_origins=["*"]`. However, when `allow_credentials=True`, you cannot use the wildcard `"*"` for `allow_origins` -- you must list specific origins. This is a CORS specification requirement, not a FastAPI limitation.

## Middleware Ordering

Middleware executes in reverse order of how it is added. The last middleware added is the first to process the request (outermost layer):

```python
app = FastAPI()

@app.middleware("http")
async def middleware_one(request: Request, call_next):
    print("Middleware 1: before")  # Runs second
    response = await call_next(request)
    print("Middleware 1: after")   # Runs third
    return response

@app.middleware("http")
async def middleware_two(request: Request, call_next):
    print("Middleware 2: before")  # Runs first
    response = await call_next(request)
    print("Middleware 2: after")   # Runs fourth
    return response
```

The output order for a request is: `Middleware 2: before`, `Middleware 1: before`, (route handler), `Middleware 1: after`, `Middleware 2: after`. This follows the standard "onion" model where each middleware wraps the next layer.

## Trusted Host Middleware

Protect against HTTP Host header attacks:

```python
from fastapi.middleware.trustedhost import TrustedHostMiddleware

app.add_middleware(
    TrustedHostMiddleware,
    allowed_hosts=["example.com", "*.example.com"],
)
```

Requests with a `Host` header not matching the allowed hosts receive a 400 Bad Request response.

## GZip Middleware

Compress responses automatically when the client supports it:

```python
from fastapi.middleware.gzip import GZipMiddleware

app.add_middleware(GZipMiddleware, minimum_size=500)
```

The `minimum_size` parameter (default: `500` bytes) sets the minimum response body size before compression is applied. Responses smaller than this threshold are sent uncompressed. GZip compression typically reduces JSON response sizes by 60-80%.

## ASGI Middleware

Since FastAPI is an ASGI application, you can use any ASGI-compatible middleware:

```python
from starlette.middleware.sessions import SessionMiddleware

app.add_middleware(
    SessionMiddleware,
    secret_key="your-session-secret",
    max_age=14 * 24 * 60 * 60,  # 14 days in seconds = 1,209,600
)
```

The `add_middleware()` method is the preferred way to add middleware in FastAPI, as it ensures proper integration with the application's middleware stack and exception handling.