Что такое middleware и как его использовать в Python?

«Что такое middleware и как его использовать в Python?» — вопрос из категории Архитектура, который задают на 10% собеседований Python Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

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

Пример использования в FastAPI:

from fastapi import FastAPI, Request, Response
import time

app = FastAPI()

@app.middleware("http")
async def add_process_time_header(request: Request, call_next):
    start_time = time.time()
    # Логика до обработки запроса (например, логирование, аутентификация)
    print(f"Request received: {request.url}")

    response = await call_next(request)

    # Логика после обработки запроса (например, добавление заголовков, сжатие)
    process_time = time.time() - start_time
    response.headers["X-Process-Time"] = str(round(process_time, 4))
    print(f"Request processed in {process_time:.4f} seconds")
    return response

@app.get("/")
async def read_root():
    return {"message": "Hello World"}

@app.get("/items/{item_id}")
async def read_item(item_id: int):
    return {"item_id": item_id}

Объяснение:

  1. Декоратор @app.middleware("http") регистрирует асинхронную функцию add_process_time_header как middleware для HTTP-запросов.
  2. request: Request — объект входящего запроса.
  3. call_next — функция, которая передает управление следующему middleware или основному обработчику маршрута. Ее вызов возвращает Response.
  4. Код до await call_next(request) выполняется до обработки запроса.
  5. Код после await call_next(request) выполняется после обработки запроса, позволяя модифицировать ответ.

Преимущества использования middleware:

  • Централизация логики: Аутентификация, логирование, обработка ошибок, добавление заголовков, сжатие ответов.
  • Повторное использование: Избегание дублирования кода в различных эндпоинтах.
  • Модульность: Легкое добавление или удаление функциональности без изменения основной бизнес-логики.