Перейти к содержанию

Middleware

🌐 Перевод выполнен с помощью ИИ и людей

Этот перевод был сделан ИИ под руководством людей. 🤝

В нем могут быть ошибки из-за неправильного понимания оригинального смысла или неестественности и т. д. 🤖

Вы можете улучшить этот перевод, помогая нам лучше направлять ИИ LLM.

Английская версия

Вы можете добавить middleware в приложения FastAPI.

"Middleware" - это функция, которая работает с каждым HTTP-запросом до его обработки какой-либо конкретной операцией пути. А также с каждым HTTP-ответом перед его возвращением.

  • Она принимает каждый HTTP-запрос, который поступает в ваше приложение.
  • Затем может что-то сделать с этим HTTP-запросом или выполнить любой нужный код.
  • Затем передаёт HTTP-запрос на обработку остальной части приложения (какой-либо операцией пути).
  • Затем принимает HTTP-ответ, сгенерированный приложением (какой-либо операцией пути).
  • Может что-то сделать с этим HTTP-ответом или выполнить любой нужный код.
  • Затем возвращает HTTP-ответ.

Технические детали

Если у вас есть зависимости с yield, то код выхода (код после yield) будет выполняться после middleware.

Если были какие‑либо фоновые задачи (рассматриваются в разделе Фоновые задачи, вы увидите это позже), они будут запущены после всех middleware.

Создание middleware

Для создания middleware используйте декоратор @app.middleware("http") поверх функции.

Функция middleware получает:

  • Объект request.
  • Функцию call_next, которая получит request в качестве параметра.
    • Эта функция передаст request соответствующей операции пути.
    • Затем она возвращает response, сгенерированный соответствующей операцией пути.
  • Затем вы можете дополнительно изменить response перед тем как его вернуть.
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"] = str(process_time)
    return response

Совет

Имейте в виду, что пользовательские проприетарные HTTP-заголовки можно добавлять с префиксом X-.

Но если у вас есть пользовательские HTTP-заголовки, которые клиент в браузере должен иметь возможность видеть, необходимо добавить их в настройки CORS (CORS (Cross-Origin Resource Sharing)), используя параметр expose_headers, описанный в документации по CORS Starlette.

Технические детали

Вы также можете использовать from starlette.requests import Request.

FastAPI предоставляет такой доступ для удобства разработчиков. Но, на самом деле, это Request из Starlette.

До и после response

Вы можете добавить код, который будет выполняться с request, до того как его получит какая-либо операция пути.

А также после формирования response, до того, как вы его вернёте.

Например, вы можете добавить собственный заголовок X-Process-Time, содержащий время в секундах, необходимое для обработки HTTP-запроса и генерации HTTP-ответа:

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"] = str(process_time)
    return response

Совет

Здесь мы используем time.perf_counter() вместо time.time() потому, что он может быть более точным для таких случаев. 🤓

Порядок выполнения нескольких middleware

Когда вы добавляете несколько middleware с помощью декоратора @app.middleware() или метода app.add_middleware(), каждое новое middleware оборачивает приложение, формируя стек. Последнее добавленное middleware — самое внешнее (outermost), а первое — самое внутреннее (innermost).

На пути обработки HTTP-запроса сначала выполняется самое внешнее middleware.

На пути формирования HTTP-ответа оно выполняется последним.

Например:

app.add_middleware(MiddlewareA)
app.add_middleware(MiddlewareB)

Это приводит к следующему порядку выполнения:

  • HTTP-запрос: MiddlewareB → MiddlewareA → маршрут

  • HTTP-ответ: маршрут → MiddlewareA → MiddlewareB

Такое стековое поведение обеспечивает предсказуемый и управляемый порядок выполнения middleware.

Другие middleware

О других middleware вы можете узнать больше позже в разделе Расширенное руководство пользователя: Продвинутое middleware.

В следующем разделе вы прочитаете, как обрабатывать CORS с помощью middleware.