В HTTP появился (точнее, вот-вот появится, только RFC приняли) новый метод QUERY.
Примерно такой:
QUERY /search
Content-Type: application/json
{
"q": "foo",
"limit": 10,
"sort": "-published"
}
И самое интересное тут даже не то, что теперь можно отправлять сложный поисковый запрос в теле HTTP-запроса. Самый интересный вопрос: а разве мы не могли делать это через GET?
Могли. Иногда даже делали.
GET /search
Content-Type: application/json
{
"q": "foo",
"limit": 10,
"sort": "-published"
}
На уровне HTTP-сообщения тело у GET возможно. Протокол не развалится только потому, что после заголовков пришёл body.
Проблема в другом: у тела GET нет нормальной общей семантики.
Стандарт не говорит: «тело GET — это параметры запроса». Сервер и клиент могут между собой так договориться, но для остальной инфраструктуры это будет частная магия. Прокси, CDN, кэши, балансировщики, библиотеки и браузерные API не обязаны понимать такой договор.
Поэтому GET с body — это поведение из серии “может работать в нашей связке”. Где-то пройдёт, где-то тело проигнорируют, где-то запрос завернут, а где-то его вообще нельзя будет отправить. Например, браузерный
fetch не разрешает body у GET и HEAD.QUERY как раз стандартизирует этот сценарий.
QUERY /search
Content-Type: application/json
{
"q": "foo",
"limit": 10,
"sort": "-published"
}
Смысл метода: это запрос на чтение, но параметры запроса лежат в теле. То есть больше не нужно притворяться, что сложный фильтр — это короткая строка query-параметров, и не нужно использовать POST там, где состояние на сервере не меняется.
От POST отличие тоже важное. POST для HTTP-инфраструктуры выглядит как метод с возможными побочными эффектами. QUERY, наоборот, описан как safe и idempotent: его можно повторить, не ожидая, что повтор сам по себе что-то создаст или изменит.
Получается, QUERY — это не «GET с body», а нормальный стандартный способ сказать: тело запроса важно, оно описывает выборку, и сам запрос при этом остаётся запросом на чтение.
#http
