Перейти до змісту

Middleware

У FastAPI можна додавати middleware.

«Middleware» — це функція, яка працює з кожним запитом перед його обробкою будь-якою конкретною операцією шляху. А також з кожною відповіддю перед її поверненням.

  • Вона отримує кожен запит, що надходить до вашого застосунку.
  • Потім вона може виконати певні дії із цим запитом або запустити необхідний код.
  • Далі вона передає запит для обробки рештою застосунку (якоюсь операцією шляху).
  • Потім вона отримує відповідь, сформовану застосунком (якоюсь операцією шляху).
  • Вона може виконати певні дії із цією відповіддю або запустити необхідний код.
  • Потім вона повертає відповідь.

Технічні деталі

Якщо у вас є залежності з yield, код виходу виконається після middleware.

Якщо були заплановані фонові задачі (розглянуто в розділі Background Tasks, ви побачите це пізніше), вони виконаються після всіх 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

Порада

Пам’ятайте, що власні пропрієтарні заголовки можна додавати використовуючи префікс X-.

Але якщо у вас є власні заголовки, які ви хочете, щоб клієнт у браузері міг побачити, потрібно додати їх до ваших конфігурацій CORS (CORS (Cross-Origin Resource Sharing)) за допомогою параметра expose_headers, описаного в документації Starlette по CORS.

Технічні деталі

Ви також можете використати from starlette.requests import Request.

FastAPI надає це для вашої зручності як розробника. Але воно походить безпосередньо зі Starlette.

До і після response

Ви можете додати код, який буде виконуватися з request, до того, як його отримає будь-яка операція шляху.

Також ви можете додати код, який буде виконуватися після того, як response буде згенеровано, перед тим як її повернути.

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

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 є зовнішнім, а перший — внутрішнім.

На шляху запиту першим виконується зовнішній middleware.

На шляху відповіді він виконується останнім.

Наприклад:

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

Це призводить до такого порядку виконання:

  • Запит: MiddlewareB → MiddlewareA → route

  • Відповідь: route → MiddlewareA → MiddlewareB

Така поведінка стеку гарантує, що middleware виконуються у передбачуваному та керованому порядку.

Інші middlewares

Ви можете пізніше прочитати більше про інші middlewares в Advanced User Guide: Advanced Middleware.

Ви дізнаєтесь, як обробляти CORS за допомогою middleware в наступному розділі.