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 в наступному розділі.