В чем разница использования middleware в FastAPI и в Django или Flask?
Что проверяют
Понимаете ли вы, на каком уровне в каждом фреймворке живёт middleware и что из этого следует: асинхронность, порядок выполнения, доступ к данным запроса. Следом почти всегда спрашивают, почему в FastAPI проверку прав лучше делать зависимостью, а не middleware.
Как отвечать
Разложите по фреймворкам:
- FastAPI: middleware здесь это ASGI-middleware из Starlette. Простой вариант: функция с декоратором
@app.middleware("http"), которая получаетrequestиcall_next. Классы подключаются черезapp.add_middleware(), так работаютCORSMiddlewareиGZipMiddleware. Последний добавленный слой оказывается внешним и первым видит запрос; - Django: список
MIDDLEWAREв настройках. Запрос идёт по нему сверху вниз, ответ снизу вверх, поэтомуAuthenticationMiddlewareобязан стоять послеSessionMiddleware. Сам middleware это фабрика, принимающаяget_response, плюс хукиprocess_viewиprocess_exception. С версии 3.1 middleware может быть асинхронным, но синхронный слой в ASGI-стеке заставляет Django адаптировать вызов на каждом запросе; - Flask: отдельного понятия middleware почти нет. Есть хуки
before_request,after_request,teardown_request, в том числе на уровне blueprint, и WSGI-обёртки вокругapp.wsgi_app, напримерProxyFixиз Werkzeug. Еслиbefore_requestвернул ответ, view уже не вызывается.
Главный вывод: в FastAPI middleware срабатывает на все маршруты и ничего не знает о конкретном эндпоинте. Логику для отдельных роутов (авторизацию, сессию БД) правильнее выносить в Depends, а middleware оставить сквозным задачам: логированию, CORS, заголовкам, request id.
Где спотыкаются
Утверждают, что Django умеет только синхронные middleware. Асинхронная поддержка есть давно, вопрос лишь в том, чтобы весь стек был асинхронным.
Читают тело запроса внутри BaseHTTPMiddleware и удивляются, что эндпоинт получил пустой поток или сломался стриминг ответа. Для таких задач пишут чистый ASGI-middleware.
Путают порядок слоёв: ставят свою проверку токена снаружи CORSMiddleware, и preflight-запросы OPTIONS отбиваются без CORS-заголовков.