Lilya получила first-class поддержку HTTP-метода QUERY
Lilya поддерживает HTTP-метод QUERY, а большинство фреймворков ещё нет.
На прошлой неделе вышла Lilya 0.27.0 с first-class поддержкой HTTP-метода QUERY. Не хелпер и не прикрученный сбоку middleware, а полноценный метод, который понимают роутер, стек middleware, тестовый клиент и генерация OpenAPI. Если вы ещё не сталкивались с QUERY, разберём, что это и почему мы сделали его полноправным методом, а не обходным путём.
Какую проблему решает QUERY
У вас read-only эндпоинт. Поиск, отчёт, фильтр. Вход это большой структурированный объект: вложенные JSON-фильтры, язык запросов, список идентификаторов на несколько сотен.
Два привычных варианта оба с изъяном.
GET кладёт всё в URL. Это ломается, как только запрос становится достаточно длинным, чтобы упереться в лимиты длины URL у клиента, прокси или сервера, и попутно сваливает ваши фильтры в каждый лог доступа и историю браузера. Тело у запроса GET на уровне протокола есть, но у него нет определённого смысла, полагаться на него нельзя.
POST принимает тело, но ничего не говорит о безопасности. Запрос POST для вызывающей стороны, прокси или кэша выглядит так, что вы, возможно, меняете состояние. Теряется сигнал "запрос безопасно повторять и кэшировать", которого заслуживает чтение.
QUERY это метод ровно для такого случая. Он определён как безопасный и идемпотентный, а его тело имеет определённый смысл. Это чтение с настоящим телом. Вы получаете тело как у POST и семантику как у GET одновременно.
Что означает "first-class" в Lilya
Роут QUERY описывается декоратором:
from lilya.apps import Lilya
from lilya.requests import Request
app = Lilya()
@app.query("/search")
async def search(request: Request):
filters = await request.json()
return {"filters": filters}
Или через общий API роутинга:
from lilya.routing import Path
routes = [
Path("/search", handler=search, methods=["QUERY"]),
]
QUERY сопоставляется как отдельный метод. Запрос GET не попадёт в роут QUERY, а запрос QUERY не попадёт в роут POST. Никакой перегрузки GET.
Тело приходит через те же request API, что и у остальных методов:
@app.query("/items")
async def items(request: Request):
query = await request.json()
return {"query": query}
У тестового клиента есть отдельный хелпер, синхронный и асинхронный:
response = client.query("/items", json={"where": {"status": "active"}})
assert response.status_code == 200
Где имитация протекла бы
Причина сделать QUERY настоящим методом, а не подделкой, это всё, что стоит за роутером.
Middleware его видит. scope["method"] и request.method оба равны "QUERY", поэтому ваш существующий middleware ведёт себя правильно, а не встречает неожиданный метод.
CSRF срабатывает верно по умолчанию. Поскольку QUERY безопасен по определению, CSRFMiddleware считает его безопасным методом, как и GET. Если бы вы имитировали QUERY через POST с телом, CSRF потребовал бы токен для чтения.
CORS его учитывает. CORSMiddleware(allow_methods=["*"]) добавляет QUERY в сгенерированный список разрешённых методов.
OpenAPI его отдаёт, используя ключ операции query в нижнем регистре, с метаданными requestBody, когда вы документируете тело.
Ничего из этого не работает, если QUERY это хак поверх фреймворка. Оно работает, потому что метод идёт по тому же пути, что и любой другой.
Ограничения
QUERY новый, а новые методы HTTP годами доходят до каждого узла на пути запроса. Документация Lilya говорит об этом прямо, скажу и я.
Часть клиентов, браузеров, прокси, шлюзов API, WAF и инструментов наблюдаемости пока не знает QUERY. Некоторым понадобится явный allow-list, некоторые откажутся принимать тело у этого метода. Проверьте весь путь запроса, прежде чем ставить эндпоинт QUERY в продакшен за обратным прокси или шлюзом.
Инструменты OpenAPI тоже отстают. Lilya отдаёт ключ операции query, но часть рендереров и генераторов клиентов пока не распознаёт его как операцию пути. Роут при этом работает, а ваш сгенерированный SDK может о нём не знать. Проверьте свой рендерер документации, прежде чем полагаться на сгенерированные клиенты для эндпоинтов QUERY.
Это цена того, чтобы быть ранним. Фреймворк поддерживает метод как надо, а экосистема вокруг ещё догоняет.
Попробовать
pip install lilya
Роут QUERY выше это вся настройка. Документация на lilya.dev, страница про QUERY подробнее разбирает семантику safe/idempotent и оговорки по прокси, исходники на github.com/dymmond/lilya.
Если ваш фреймворк до сих пор заставляет выбирать между переполненным URL и запросом POST, который врёт про то, что он мутация, то это тот пробел, который метод закрывает.
Авторизуйтесь, чтобы оставить комментарий.
Нет комментариев.
Тут может быть ваша реклама
Пишите info@aisferaic.ru