Что такое middleware в FastAPI и для чего оно используется

Ответ

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

Оно используется для сквозной функциональности, применяемой ко многим или всем эндпоинтам. Основная польза — вынесение общей логики из обработчиков, что делает код чище и позволяет избежать дублирования.

Основные сценарии использования:

  • Логирование: запись информации о каждом запросе и ответе.
  • Аутентификация: проверка токенов или сессий.
  • Обработка CORS: добавление необходимых заголовков.
  • Измерение времени выполнения: отслеживание производительности запросов.
  • Обработка ошибок: централизованный перехват исключений.

Пример middleware для логирования:

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.time()

    # Передача запроса следующему middleware или обработчику пути
    response = await call_next(request)

    # Код, который выполняется после обработки запроса
    process_time = time.time() - start_time
    response.headers["X-Process-Time"] = str(process_time)
    print(f"Запрос {request.method} {request.url.path} выполнен за {process_time:.4f} сек")

    return response

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

В этом примере call_next(request) — это вызов следующего звена в цепочке обработки. Все, что находится до этого вызова, выполняется на пути "внутрь" приложения, а все, что после, — на пути "наружу".

Ответ 18+ 🔞

А, слушай, про middleware в FastAPI! Это же, блядь, как швейцар в дорогом отеле, только для твоего кода, понимаешь? Он стоит на пороге каждого запроса и говорит: "Стой, мудила, куда прешь? Сначала через меня пройди!"

Ну, если по-человечьи, то это такая функция-надзиратель, которая ловит каждый входящий запрос, ещё до того как он доползёт до твоего основного обработчика-роута. И обратно, когда ответ уже готов, она его тоже по головке гладит перед отправкой. Польза-то какая? Овердохуищная! Всякую общую, сквозную хуйню в одно место засунуть, чтобы не копипастить одно и то же в каждом эндпоинте.

Где это, блядь, пригождается? Да везде!

  • Логирование: Чтобы записывать, кто, когда и с каким запросом приходил. А то потом, когда всё ебнется, будешь как дурак в потолок плевать — "а что, сука, случилось-то?"
  • Аутентификация: Проверка, а свой ли это человек стучится, или левый пидор с улицы. Токены там всякие, сессии.
  • CORS: Ну, это чтобы браузеры не орали "ой, ой, не могу!" когда твой фронтенд с другого домена стучится.
  • Замер времени: Посмотреть, не тормозит ли какой-нибудь запрос, как черепаха в сиропе.
  • Обработка ошибок: Чтобы не размазывать try...except по всему коду, а ловить всё в одном месте. Красота, ёпта!

Вот, смотри, пример middleware для логирования, простой как три копейки:

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.time()

    # А это — магическая палочка! Передаём запрос дальше по цепочке
    response = await call_next(request)

    # А тут мы уже ПОСЛЕ того, как запрос обработали, ловим ответ
    process_time = time.time() - start_time
    response.headers["X-Process-Time"] = str(process_time)
    print(f"Запрос {request.method} {request.url.path} выполнен за {process_time:.4f} сек")

    return response

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

Видишь, в чём фокус? Вся магия вокруг этого call_next(request). Всё, что до него — это как раз путь запроса внутрь приложения. А всё, что после — это уже он, бедолага, вылезает обратно с ответом. И ты его в этот момент ещё и по головке погладить можешь, заголовки ему навешать. Удобно же, блядь! В рот меня чих-пых, гениальная просто штука.