Articles

Lilya получила first-class поддержку HTTP-метода QUERY

Lilya получила first-class поддержку HTTP-метода QUERY
Михаил Омельченко
Автор
Михаил Омельченко
Опубликовано 15.07.2026
0,0
Views 1

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, который врёт про то, что он мутация, то это тот пробел, который метод закрывает.

Авторизуйтесь, чтобы оставить комментарий.

Комментариев: 0

Нет комментариев.

Тут может быть ваша реклама

Пишите info@aisferaic.ru

Похожие статьи