Это отдельный метод для сложной фильтрации/поиска с телом, который позволит не использовать для этого POST.
Раньше для фильтрации нам были доступны:
➡️ GET с query-параметрами:
GET /products?priceFrom=1000&priceTo=5000
➕ Правильная семантика - получение данных
➕ Идемпотентный
➕ Ответ может кэшироваться
➖ Если много параметров, URL получается длинный, а на прокси и балансировщиках могут быть ограничения на длину URL
➖ Неудобно для чтения
➡️ POST c телом
POST /orders/search
{
"statuses": ["PAID", "SHIPPED"],
"createdAt": {
"from": "2026-08-01",
"to": "2026-08-18"
},
"customerName": "Иван"
}
➕ Можно передать в теле много параметров, а URL останется коротким
➕ Удобно для чтения и обработки
➖ POST по семантике HTTP не является идемпотентным. Саму операцию на бэке мы можем реализовать идемпотентно, но HTTP-клиенты и промежуточная инфраструктура не могут сделать такой вывод из запроса и поэтому не будут повторять его в случае сбоя
➖ Обычно не кэшируется
Про кэширование хочу развернуть чуть подробнее. Под кэшируемостью в таких сравнениях обычно имеется в виду кэш на API Gateway, прокси, CDN или на клиенте. Не наш условный Redis на бэке. В своем Redis мы можем любое кэширование сделать, если надо, а тут скорее про общие настройки инфраструктуры.
Промежуточный кэш может запоминать ответ GET, например, на 60 секунд и при повторном таком GET не обращаться на бэк, а отдавать ответ из кэша (для снижения нагрузки на бэк).
POST-запросы теоретически можно кэшировать, но следующий такой же POST нельзя просто обслужить этим сохраненным ответом. Он может использоваться для будущего GET, а сам POST считается потенциально изменяющим состояние и должен быть передан на бэк. Поэтому для сценария: один POST /search, потом такой же POST /search обычное HTTP-кэширование не работает.
➡️ С QUERY мы можем передавать то же тело, что в POST, но с явным методом QUERY, так что он комбинирует плюсы обоих подходов:
QUERY /orders
{
"statuses": ["PAID", "SHIPPED"],
"createdAt": {
"from": "2026-08-01",
"to": "2026-08-18"
},
"customerName": "Иван"
}➕ Правильная семантика
➕ Идемпотентный
➕ Можно передать в теле много параметров, а URL останется коротким
➕ Удобно для чтения и обработки
➕ Может кэшироваться (если инфраструктура знает про новый метод)
Кэширование QUERY должно учитывать не только URL, как обычно у GET, но и содержимое тела и метаданные вроде Content-Type (это прямо предусмотрено RFC 10008)
Условно если cache key:
QUERY + /orders + {"customerName":"Иван"}Тогда запрос для Егора:
QUERY /orders
{
"customerName": "Егор"
}не получит из кэша ответ для Ивана.
➖ Пока не везде поддерживается
Если вы не пишете на Go, то скорее всего внедрять QUERY пока рано: на уровне многих фреймворков он еще не поддерживается.
Например, в Spring поддержку QUERY хотят добавить в Spring Framework 7.1, но PR пока в работе: буквально вчера по нему запросили изменения, а полноценную поддержку кэширования QUERY решили пока отложить.
Обходной путь принимать такие запросы есть, но кажется, что пока нет причин торопиться.
Я не гошница, но насколько могу судить в Go ситуация проще: в net/http метод задается просто string, без enum, поэтому можно указать "QUERY" и принимать новые запросы уже сейчас. Но полной поддержки RFC тоже еще нет.
Какой подход к фильтрации вам привычнее: c GET или POST?
Я привыкла к фильтрам в виде POST /search.
Может вы встречали какие-то необычные подходы к фильтрации?
Я встречала один довольно хлопотный для бэка подход, больше похожий на мини-DSL, расскажу в комментах.
Планируете ли внедрять QUERY в апишки, когда его поддержат фреймворки?