← Назад к вопросам

Зачем нужен Middleware в FastAPI?

2.0 Middle🔥 141 комментариев
#FastAPI и Flask

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Middleware в FastAPI

Middleware — это функции, которые обрабатывают каждый запрос перед его попаданием в обработчик (handler) и каждый ответ после обработки. Это мощный инструмент для кросс-функциональной логики.

Основная концепция

Middleware работает по принципу луковицы (onion layers):

Запрос → Middleware 1 → Middleware 2 → Handler → Middleware 2 → Middleware 1 → Ответ

Каждый middleware может:

  1. Модифицировать запрос перед передачей в handler
  2. Перехватить исключения и вернуть свой ответ
  3. Модифицировать ответ перед отправкой клиенту
  4. Выполнить логику как до, так и после обработки запроса

Зачем нужны Middleware

1. Логирование всех запросов и ответов:

from fastapi import FastAPI, Request
import time
import logging

logger = logging.getLogger(__name__)
app = FastAPI()

@app.middleware("http")
async def log_middleware(request: Request, call_next):
    start_time = time.time()
    
    # Логируем входящий запрос
    logger.info(f"Request: {request.method} {request.url}")
    
    # Передаём в обработчик
    response = await call_next(request)
    
    # Логируем время обработки и ответ
    process_time = time.time() - start_time
    logger.info(f"Response: {response.status_code} (took {process_time:.3f}s)")
    
    # Добавляем header с временем обработки
    response.headers["X-Process-Time"] = str(process_time)
    return response

2. Аутентификация и авторизация:

from fastapi import FastAPI, Request, HTTPException
from fastapi.responses import JSONResponse

@app.middleware("http")
async def auth_middleware(request: Request, call_next):
    # Пропускаем публичные endpoints
    if request.url.path in ["/api/auth/login", "/api/health"]:
        return await call_next(request)
    
    # Проверяем токен
    token = request.headers.get("Authorization")
    if not token or not validate_token(token):
        return JSONResponse(
            status_code=401,
            content={"error": "Unauthorized"}
        )
    
    return await call_next(request)

3. Добавление заголовков безопасности:

@app.middleware("http")
async def security_headers_middleware(request: Request, call_next):
    response = await call_next(request)
    
    # Добавляем security headers
    response.headers["X-Content-Type-Options"] = "nosniff"
    response.headers["X-Frame-Options"] = "DENY"
    response.headers["X-XSS-Protection"] = "1; mode=block"
    response.headers["Strict-Transport-Security"] = "max-age=31536000; includeSubDomains"
    
    return response

4. CORS (Cross-Origin Resource Sharing):

from fastapi.middleware.cors import CORSMiddleware

app.add_middleware(
    CORSMiddleware,
    allow_origins=["https://example.com", "https://app.example.com"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

5. Обработка исключений:

from fastapi.responses import JSONResponse
import traceback

@app.middleware("http")
async def exception_middleware(request: Request, call_next):
    try:
        response = await call_next(request)
    except Exception as exc:
        logger.error(f"Unhandled exception: {traceback.format_exc()}")
        return JSONResponse(
            status_code=500,
            content={"error": "Internal Server Error"}
        )
    return response

6. Добавление контекста к запросу:

from fastapi import Request
import uuid

@app.middleware("http")
async def request_id_middleware(request: Request, call_next):
    # Генерируем уникальный ID для запроса
    request_id = str(uuid.uuid4())
    request.state.request_id = request_id
    
    response = await call_next(request)
    response.headers["X-Request-ID"] = request_id
    return response

Порядок выполнения Middleware

Мiddleware выполняются в порядке добавления:

app.add_middleware("http", CORSMiddleware)      # Выполняется первым
app.add_middleware("http", AuthMiddleware)      # Выполняется вторым
app.add_middleware("http", LoggingMiddleware)   # Выполняется третьим

Ответы проходят в обратном порядке:

Запрос → CORS → Auth → Logging → Handler
Ответ ← CORS ← Auth ← Logging ← Handler

Встроенные Middleware в FastAPI

from fastapi.middleware.cors import CORSMiddleware
from fastapi.middleware.gzip import GZIPMiddleware
from fastapi.middleware.trustedhost import TrustedHostMiddleware

# GZip сжатие ответов
app.add_middleware(GZIPMiddleware, minimum_size=1000)

# Защита от CSRF и других атак
app.add_middleware(TrustedHostMiddleware, allowed_hosts=["example.com"])

Best Practices

✅ Делай:

  • Логируй все важные события
  • Обрабатывай исключения на верхнем уровне
  • Добавляй security headers
  • Используй request_id для трейсирования
  • Оптимизируй производительность (избегай тяжелых операций)

❌ Не делай:

  • Не выполняй долгие синхронные операции в middleware
  • Не обращайся в БД без необходимости
  • Не логируй сенситивные данные (пароли, токены)

Пример комплексного middleware

import time
import logging
from fastapi import FastAPI, Request
from fastapi.responses import JSONResponse

logger = logging.getLogger(__name__)

@app.middleware("http")
async def comprehensive_middleware(request: Request, call_next):
    # 1. Добавляем request_id
    request_id = request.headers.get("X-Request-ID", str(uuid.uuid4()))
    
    # 2. Логируем начало
    start_time = time.time()
    logger.info(f"[{request_id}] {request.method} {request.url.path}")
    
    try:
        # 3. Вызываем обработчик
        response = await call_next(request)
    except Exception as exc:
        # 4. Обрабатываем исключение
        logger.error(f"[{request_id}] Error: {exc}")
        return JSONResponse(status_code=500, content={"error": "Server error"})
    
    # 5. Добавляем headers
    process_time = time.time() - start_time
    response.headers["X-Process-Time"] = str(process_time)
    response.headers["X-Request-ID"] = request_id
    
    # 6. Логируем завершение
    logger.info(f"[{request_id}] {response.status_code} ({process_time:.3f}s)")
    
    return response

Вывод

Middleware в FastAPI — это критический инструмент для:

  • Безопасности (аутентификация, CSRF защита, security headers)
  • Наблюдаемости (логирование, трейсирование, мониторинг)
  • Производительности (кеширование, сжатие)
  • Обработки ошибок (глобальная обработка исключений)

Правильное использование middleware позволяет держать code чистым и отделить кросс-функциональную логику от бизнес-логики.