Каков жизненный цикл обработки HTTP-запроса в FastAPI

«Каков жизненный цикл обработки HTTP-запроса в FastAPI» — вопрос из категории Библиотеки и модули, который задают на 10% собеседований Python Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

FastAPI, построенный на ASGI-фреймворке Starlette и библиотеке Pydantic, обрабатывает запросы в несколько четких и высокопроизводительных этапов.

Жизненный цикл запроса:

  1. Маршрутизация (Routing)

    • Starlette получает входящий HTTP-запрос.
    • Он сопоставляет HTTP-метод (GET, POST и т.д.) и путь запроса (например, /items/1) с соответствующей функцией-обработчиком (path operation function), определенной с помощью декоратора (@app.get("/items/{item_id}")).
  2. Извлечение и Валидация (Parsing & Validation)

    • FastAPI использует Pydantic для автоматического парсинга, приведения типов и валидации данных.
    • Данные извлекаются из пути, query-параметров, заголовков, cookie и тела запроса.
    • Если данные не соответствуют аннотациям типов или валидаторам в модели Pydantic, FastAPI автоматически прерывает цикл и возвращает клиенту ошибку 422 Unprocessable Entity с подробным JSON-описанием проблемы.
  3. Обработка Зависимостей (Dependency Injection)

    • FastAPI выполняет все зависимости, указанные для эндпоинта с помощью Depends.
    • Это может включать проверку аутентификации, получение сессии базы данных или выполнение другого общего кода.
    • Результаты выполнения зависимостей передаются в функцию-обработчик в качестве аргументов.
  4. Выполнение Кода Эндпоинта (Path Operation Execution)

    • Вызывается сама функция-обработчик с уже валидированными данными и результатами работы зависимостей.
    • FastAPI эффективно обрабатывает как асинхронные (async def), так и синхронные (def) функции. Синхронные функции выполняются в отдельном пуле потоков, чтобы не блокировать основной цикл событий (event loop).
  5. Формирование Ответа (Response Generation)

    • Результат, возвращаемый функцией, сериализуется (обычно в JSON).
    • FastAPI упаковывает данные в HTTP-ответ с соответствующим статус-кодом, заголовками и телом.

Пример с валидацией:

from fastapi import FastAPI
from pydantic import BaseModel, Field

app = FastAPI()

class Item(BaseModel):
    name: str
    price: float = Field(..., gt=0) # Цена должна быть больше нуля

@app.post("/items/")
async def create_item(item: Item):
    # Этот код выполнится только если 'item' пройдет валидацию Pydantic
    return {"status": "success", "item": item}

Если отправить POST-запрос с {"name": "Apple", "price": -1}, FastAPI автоматически вернет ошибку 422 еще до вызова функции create_item.