HTTP QUERY: почему поиск больше не должен притворяться методом POSTПоисковый фильтр в API давно перестал быть парой простых параметров — это дерево условий, массивы идентификаторов, диапазоны дат и состояние пагинации. В GET всё это пришлось бы кодировать в URI.
Стандарт HTTP советует поддерживать адреса длиной хотя бы 8 000 байт, но лимит у каждого звена свой. Поэтому длинный URL может обрезать браузер, балансировщик или WAF ещё до сервиса. Даже если адрес прошёл всю цепочку, он раздувается от percent-encoding и целиком оседает в логах и истории браузера.
Почти каждый поиск в API живёт как POST /search. Для протокола это обычный POST: он небезопасный и неидемпотентный, поэтому прокси не имеет права повторить оборванный запрос, кеш — переиспользовать такой ответ, а клиент с retry рискует задублировать операцию.
Что предложил RFC 10008В июне 2026 года IETF опубликовал
RFC 10008 с методом QUERY. Метод объединяет безопасность и идемпотентность GET с телом запроса, как у POST.
QUERY /feed HTTP/1.1
Host: api.example.test
Content-Type: application/json
{
"filter": {
"status": ["published", "scheduled"], # допустимые статусы
"publishedAt": { "gte": "2026-01-01" } # нижняя граница даты
},
"sort": [{ "field": "publishedAt", "direction": "desc" }],
"limit": 50
}
URI здесь задаёт ресурс и область выборки, а filter и sort в теле описывают условия поиска. Называть QUERY «GET с телом» неточно, ведь у тела GET нет определённой семантики, а у QUERY оно определяет всю операцию. Content-Type при этом обязателен: без него сервер отклоняет запрос, а угадывать формат по содержимому запрещено.
КешированиеКлюч кеша обязан включать URI, тело запроса и Content-Type, поэтому запросы с "page": 1 и "page": 2 не могут делить одну запись. Чтобы построить ключ, кешу сначала придётся прочитать всё тело, и кеширование QUERY выходит дороже, чем GET.
Если запрос тяжёлый, сервер может вернуть Location с адресом сохранённого запроса. Тогда последующие обращения пойдут обычным GET, без повторной передачи тела.
Что с поддержкой?OpenAPI 3.2 уже описывает query как first-class операцию. Серверные фреймворки подтягиваются с разной скоростью. Spring Framework 7.1 содержит HttpMethod.QUERY, заголовок Accept-Query и привязку тела запроса. В Gin и Fiber поддержка появилась в upstream, а Fastify и NestJS пока остановились на issues.
Инфраструктура отстаёт от фреймворков. NGINX уже проксирует QUERY, но не кеширует его, потому что proxy_cache_methods по умолчанию ограничен GET, HEAD и POST. В браузерах метод не входит в CORS-safelist, поэтому междоменный вызов требует preflight, а HTML-формы method="query" не стандартизированы.
QUERY закрывает старый разрыв между GET и POST, но сам стандарт не заставляет промежуточные звенья его понимать. Перед продом прогоняйте всю цепочку на реальном трафике и держите POST /search как фолбэк.
#backendvkhub #api #поиск