Промежуточное ПО FastAPI
Промежуточное ПО — это функция, которая выполняется до и после того, как каждый запрос достигнет обработчика маршрута.
Промежуточное ПО можно использовать для общей логики, такой как добавление логов, изменение запросов/ответов, обработка CORS и т. д.
Как работает промежуточное ПО
Поток выполнения промежуточного ПО:
- Запрос достигает промежуточного ПО
- Промежуточное ПО выполняет логику предварительной обработки
- Промежуточное ПО передаёт запрос следующему промежуточному ПО или функции маршрута.
- Функция маршрута возвращает ответ
- Middleware выполняет логику постобработки
- Ответ возвращается клиенту

| Name | Функция |
|---|---|
| Клиент | Браузеры, фронтенд-приложения, Postman и т. д. отправляют HTTP-запросы в FastAPI |
| Запрос | Объект HTTP-запроса, содержащий такие данные, как URL, Header, Body, Cookie |
| Middleware 1 | Первый слой обработки после поступления запроса |
| Middleware 2 | Логика обработки второго слоя |
| Middleware N | Несколько middleware выполняются по порядку |
| Функция-обработчик маршрута (Path Operation) | Место, где фактически выполняется бизнес-код |
| Фаза ответа | После того как маршрут возвращает Response, ответ снова проходит через промежуточное ПО. |
| Промежуточное ПО возвращается в обратном порядке | Ответы возвращаются в "обратном порядке" |
| Response response | Данные, которые в конечном итоге возвращаются клиенту |
Создание промежуточного ПО
Использование@app.middleware("http")Создание промежуточного ПО с помощью декораторов:
Пример
from fastapi import FastAPI, Request
app = FastAPI()
@app.middleware("http")
async def add_process_time_header(request: Request, call_next):
# 1. Предварительная обработка запроса: записать время начала
start_time = time.time()
# 2. Передайте запрос следующему middleware или функции маршрута
response = await call_next(request)
# 3. Обработка после ответа: вычислить время обработки и добавить заголовки ответа.
process_time = time.time() - start_time
response.headers["X-Process-Time"] = str(process_time)
return response
@app.get("/")
async def root():
return {"message": "Hello World"}
Пояснение к коду:
| Часть | Описание |
|---|---|
@app.middleware("http") | Объявите это как HTTP middleware. |
request: Request | Текущий объект запроса |
call_next | Функция обратного вызова, которая вызывает следующий middleware или функцию маршрута. |
await call_next(request) | Передайте запрос следующему слою и получите ответ |
call_nextПолучениеrequestПараметры и возвращаемое значениеresponse. Вы можете вызватьcall_nextИзмените запрос перед вызовом и измените ответ после вызова.
Промежуточное ПО для логирования запросов
Следующее промежуточное ПО регистрирует базовую информацию о каждом запросе:
Пример
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):
# Записать информацию о запросе
logger.info(fЗапрос: {request.method} {request.url})
start_time = time.time()
response = await call_next(request)
process_time = time.time() - start_time
# Записать информацию об ответе
logger.info(
f"Ответ: {request.method} {request.url} "
fКод состояния={response.status_code} затраченное время={process_time:.3f}s
)
return response
Порядок выполнения промежуточного ПО
Промежуточное ПО выполняется в порядке регистрации; запросы проходят через промежуточное ПО в прямом порядке, а ответы — в обратном порядке:
请求 -> 中间件A(前) -> 中间件B(前) -> 路由函数 响应 <- 中间件A(后) <- 中间件B(后) <- 路由函数
Порядок регистрации промежуточного ПО важен. Если у вас есть два промежуточных ПО A и B, и сначала регистрируется A, запрос проходит сначала через A, затем через B, но ответ проходит сначала через B, затем через A.
Использование встроенного промежуточного ПО Starlette
FastAPI наследуется от Starlette, поэтому промежуточное ПО, предоставляемое Starlette, можно использовать напрямую:
Пример
from starlette.middleware.httpsredirect import HTTPSRedirectMiddleware
app = FastAPI()
# Принудительное перенаправление на HTTPS
app.add_middleware(HTTPSRedirectMiddleware)
@app.get("/")
async def root():
return {"message": Доступ с использованием HTTPS}
Распространённое встроенное промежуточное ПО:
| Промежуточное ПО | Описание |
|---|---|
HTTPSRedirectMiddleware | Принудительно перенаправлять HTTP-запросы на HTTPS |
TrustedHostMiddleware | Ограничить разрешённые имена хостов |
GZipMiddleware | Автоматически сжимать содержимое ответа |
CORSMiddleware | Обработка кросс-доменных запросов (подробно в следующей главе) |
Промежуточное ПО для GZip-сжатия
Включение GZip-сжатия может уменьшить размер ответа и повысить скорость передачи:
Пример
from fastapi.middleware.gzip import GZipMiddleware
app = FastAPI()
# Автоматически сжимать, когда размер ответа превышает 1000 байт
app.add_middleware(GZipMiddleware, minimum_size=1000)
@app.get("/")
async def root():
return {"message": "Этот ответ может быть сжат с помощью GZip"}
Итог
- Промежуточное ПО выполняет общую логику в цепочке обработки запроса/ответа.
- Использование
@app.middleware("http")Создание собственного промежуточного ПО call_next(request)Передать запрос на следующий слой- Промежуточное ПО выполняется в порядке регистрации (запросы — в прямом порядке, ответы — в обратном порядке)
- FastAPI/Starlette предоставляет встроенное промежуточное ПО, такое как CORS, GZip, перенаправление на HTTPS и т. д.