LINUX.ORG.RU

Стандартизирован HTTP-метод QUERY, комбинирующий возможности GET и POST

 , , ,


1

4

Инженерный комитет IETF (Internet Engineering Task Force), занимающийся развитием протоколов и архитектуры сети Интернет, придал HTTP-методу QUERY статус «Предложенного стандарта» и опубликовал связанную с ним спецификацию RFC 10008. Метод QUERY по способу отправки данных на сервер повторяет метод POST, но отличается от него ориентацией не на запись данных и изменение состояния, а на формирование запросов на чтение.

По решаемым задачам новый метод близок к GET и позволят отправлять запросы, которые могут быть повторены или перезапущены без изменения состояния на сервере. Как и в методе POST параметры запроса в QUERY передаются не в URI, а в теле запроса. Подобный подход даёт возможность передавать большой объём параметров в запросе, превышающий лимит на размер параметров в методе GET (8000 байт).

GET /feed?q=foo&limit=10&sort=-published HTTP/1.1
Host: example.org

QUERY /feed HTTP/1.1
Host: example.org
Content-Type: application/x-www-form-urlencoded

q=foo&limit=10&sort=-published

Отправленные через метод QUERY параметры не отражаются в логах серверов, что с одной стороны затрудняет анализ запросов и диагностику проблем, но с другой стороны даёт возможность скрыть конфиденциальные данные из логов прокси-серверов.

Среди областей применения метода QUERY упоминается отправка запросов к Web API, выдающих результат в формате JSON или XML, или бэкендам, генерирующим контент. Для определения возможности использования нового метода при обращении к серверу предлагается использовать метод OPTIONS, а для определения поддерживаемых форматов метод HEAD:

> OPTIONS /contacts HTTP/1.1
> Host: example.org

HTTP/1.1 200 OK
Allow: GET, QUERY, OPTIONS, HEAD

В методе QUERY предусмотрена поддержка кэширования — прокси-серверы или обработчики могут сохранить результат выполнения запроса, присвоить ему URI для последующего обращения через метод GET и вернуть информацию о выдаче прокэшированной версии через заголовок Last-Modified. Для проверки наличия изменений с прошлого запроса может применяться заголовок If-Modified-Since. Для указания альтернативных вариантов выполнения запроса в ответе могут указываться заголовки Content-Location и Location, отличия которых в том, что первый передаёт ссылку для получения результата ранее выполненного запроса, а второй предназначен для повторения запроса с теми же параметрами:

> QUERY /contacts HTTP/1.1
> Host: example.org
> Content-Type: application/x-www-form-urlencoded
> Accept: application/json
> select=surname,givenname,email&limit=10&match=%22email=*@example.*%22

HTTP/1.1 200 OK
Content-Type: application/json
Content-Location: /contacts/stored-results/17
Location: /contacts/stored-queries/42
Last-Modified: Sat, 25 Aug 2012 23:34:45 GMT
Date: Sun, 17 Nov 2024, 16:10:24 GMT

> GET /contacts/stored-results/17 HTTP/1.1
> Host: example.org
> Accept: application/json

Помимо типа application/x-www-form-urlencoded для передачи параметров в запросах QUERY также могут напрямую использоваться расширенные форматы, такие как JSONPath (application/jsonpath), XSLT (application/xslt+xml) и SQL (application/sql). Поддерживаемые форматы возвращаются сервером в заголовке Accept-Query.

> HEAD /contacts HTTP/1.1
> Host: example.org

HTTP/1.1 200 OK
Content-Type: application/xhtml
Accept-Query: application/x-www-form-urlencoded, application/jsonpath, application/sql

> QUERY /errata.json HTTP/1.1
> Host: example.org
> Content-Type: application/jsonpath
> Accept: application/json
>
> $..[
>     ?@.errata_status_code=="Rejected"
>     && @.submit_date>"2024"
>   ]
>   ["doc-id"]

>>> Источник: OpenNET

★★★★★

Проверено: maxcom ()
Ответ на: комментарий от gobot

Большинство сайтов шлют штатным способом. Всякие модные словечки использует меньшинство.

firkax ★★★★★
()

А просто официально разрешить тело запроса у GET (а то ЕМНИП некоторые броузеры его режут) – не вариант было?

dimgel ★★★★★
()
Ответ на: комментарий от dimgel

Его официально никто и не запрещал. Я тоже не понимаю, зачем придумывать новый запрос, если GET прекрасно можно использовать с телом здесь и сейчас (я лично использовал). Но в HTTP много всякой псевдо-семантический фигни. Это как в HTML - придумали миллион тегов, а по факту все дивами просто верстают и в ус не дуют.

vbr ★★★★★
()
Ответ на: комментарий от annulen

Возможно, это стало актуально в связи с тем, что Интернета сейчас нет, а есть Cloudflare?

Кстати, хорошей альтернативой-дополнением было бы стандартизировать 503 код (сделать какой-нибудь 513), дав ему семантику «запрос не могу обработать, но можно его повторить».

allter149
()
Ответ на: комментарий от vbr

зачем придумывать новый запрос, если GET прекрасно можно использовать с телом здесь и сейчас

Существующие механизмы кэшировантия GET’а игнорируют тело запроса.

r--r--r--
()
Ответ на: комментарий от r--r--r--

Существующие механизмы кэширования вообще не пойми как работают с QUERY запросом. Так и так надо их дописывать.

vbr ★★★★★
()
Ответ на: комментарий от r--r--r--

Проверяю Check Expiry History = 2 и Always Reload HTTPS In History = true.

Или неправильно проверяю, или всё-таки не вру и работает кэш на POST в Opera12.

Toxo2 ★★★★★
()
Последнее исправление: Toxo2 (всего исправлений: 1)
Ответ на: комментарий от Toxo2

Я тебя не понял. Подними POST-сервер и сделай на него два POST’а из оперы. Если кэширование работает, должен придти только один запрос.

r--r--r--
()
Последнее исправление: r--r--r-- (всего исправлений: 2)
Ответ на: комментарий от vbr

Существующие механизмы кэширования вообще не пойми как работают с QUERY запросом.

Они с ним никак не работают, потому что его не существует сейчас.

r--r--r--
()
Ответ на: комментарий от annulen

Все сложнее, потому что есть безопасные запросы и есть опасные. Гет - безопасный, пост - нет. Пост не кешируется, потому что предполагается, что post изменяет состояние на сервере, это первое. Второе - браузер не будет делать крос сайтовые запросы на другой домен с пост запросом (часто поиск какой-то работает через post) без настройки CORS, потому что это прямой путь своровать бабки у тебя с банковского аккаунта, сделав POST sb.rf/transfer.php?amount=2000&to=1243-4321-4321-1234. Тут хотят обойти эти ограничения, введя GET с параметрами в теле, но безопасный

masa ★★★
()

По решаемым задачам новый метод близок к GET

Жаль только ссылку нельзя будет дать, этим часто пренебрегают, передавая какие-то фильтры через POST

goingUp ★★★★★
()
Последнее исправление: goingUp (всего исправлений: 1)
Ответ на: комментарий от masa

Гет - безопасный, пост - нет.

Это верно только в рамках концепции ReST. Наша контора работала в парадигме RPC и никого не смущало, что «POST - это когда в GET слишком много аргументов»

Пост не кешируется, потому что предполагается, что post изменяет состояние на сервере, это первое

Это всего лишь поведение по-умолчанию и легко настраивается заголовками кэширования

Второе - браузер не будет делать крос сайтовые запросы на другой домен с пост запросом (часто поиск какой-то работает через post) без настройки CORS

Так себе аргумент, с кросс-сайтовыми вещами без знания CORS лучше не связываться

annulen ★★★★★
()
Ответ на: комментарий от masa

Все сложнее, потому что есть безопасные запросы и есть опасные. Гет - безопасный

Вот не всегда: https://docs.rukovoditel.net.ru/img/1562066957_telephony_settings.png. Добавление информации о произошедшем звонке происходит через GET.

И даже у формы (тега FORM) по умолчанию method=GET.

monk ★★★★★
()
Ответ на: комментарий от monk

Добавление информации о произошедшем звонке происходит через GET.

Оно может и через DELETE происходить, если разработчики так сделают. Это уже на стороне того, кто и как насрал на стандарты и конвенции.

И даже у формы (тега FORM) по умолчанию method=GET.

Это потому что веб-форма по умолчанию запрашивает информацию с сервера, а не создаёт на сервере новые объекты.

r--r--r--
()
Последнее исправление: r--r--r-- (всего исправлений: 1)
Ответ на: комментарий от skyman

А чем длиннющий URL принципиально хуже, чем короткий URL, но с телом запроса?

По-моему, это замена шила на мыло :)

PeleWin
()
Ответ на: комментарий от vbr

Мне кажется, логика в том, что существует огромная куча ПО, обрабатывающего HTTP-запросы. И всё это ПО потребуется переписать, добавив в метод GET соответствующую поддержку тела запроса. А как отличить ПО, которое поддерживает GET с телом запроса от того, которое не поддерживает? Непонятно.

В случае же с QUERY это новый метод, наличие или отсутствие поддержки которого проверить, скорее всего, проще: при отсутствии поддержки нового метода будет возвращено что-то вроде «400 Bad request».

P.S. Правда, сейчас я попробовал с помощью telnet отправить QUERY-запрос (а также уж точно не поддерживаемый QWERTYUIOP-запрос) и в ответ оба раза получил то же самое, что при обычном GET, безо всяких ошибок :)

PeleWin
()
Последнее исправление: PeleWin (всего исправлений: 1)

Один хер в кровавом будет пост для всего

Lordwind ★★★★★
()
Ответ на: комментарий от PeleWin

А чем длиннющий URL принципиально хуже, чем короткий URL, но с телом запроса?

Очевидно разделением сущностей. Путь - в одном месте, тело в другом. Обрабатывать проще, дебажить проще.

Иначе можно было бы в урл сразу и хедеры класть, и куки, чего уж там.

skyman ★★★★★
()
Ответ на: комментарий от r--r--r--

Так может стоило расширить определение обработки GET, вместо того чтобы городить ещё один запрос?

Один хрен механизмы кэширования переписывать надо будет.

WatchCat ★★★★★
()
Ответ на: комментарий от r--r--r--

Существующие для GET’а - нет. Там ничего не меняется.

Тут просто выбор, либо менять существующие для имеющегося, либо писать новые для нового запроса. А зачем городить новое, если можно изменить старое?

WatchCat ★★★★★
()

Посмотрим, приживется ли новый стандарт. Но если и да, то вряд ли скоро

Подобный подход даёт возможность передавать большой объём параметров в запросе, превышающий лимит на размер параметров в методе GET (8000 байт).

ЕМНИП, этот лимит сейчас обходят через куки. Например, в kibana / opensearch dashboard

router ★★★★★
()
Ответ на: комментарий от skyman

Не, куки в url нельзя. Это ж утечка всего вообще куда попало через referer

router ★★★★★
()
Последнее исправление: router (всего исправлений: 1)
Ответ на: комментарий от WatchCat

А зачем городить новое, если можно изменить старое?

Именно для этого. Чтобы не версионировать старое.

monk ★★★★★
()

Нужно

В REST приложении куча запросов на получения списков с фильтрами, которые хочется передавать как JSON дабы не заморачиваться с false null угадыванием, приходится пользовать POST. С другой стороны нужна поддержка readonly impersonation для админа, где запрещаем все запросы кроме GET с auth token юзера под которым мы заходим.

aeroflot
()
Ответ на: комментарий от maxcom

Хорошая идея. Например в API у Elasticsearch / OpenSearch как раз ощущается нехватка такого метода.

kibana - settings - advanced settings - Store URLs in session storage

state:storeInSessionStorage

в opensearch dashboards примерно там же

При этом параметры лежат в куках. Но это как была экспериментальная фича, так и осталась. При открытии url черезе несколько дней куки протухают и веб-морда выдает ошибку. Ошибку можно закрыть и перезагрузить страницу. Неудобно, но работает

router ★★★★★
()
Ответ на: комментарий от WatchCat

В общем по сути можно было и GET с телом использовать. И POST использовать, тут в теме уже приводили заголовки, позволяющие POST кешировать. Но решили придумать новое. Ну ладно.

vbr ★★★★★
()
Ответ на: комментарий от vbr

В общем по сути можно было и GET с телом использовать. И POST использовать, тут в теме уже приводили заголовки, позволяющие POST кешировать. Но решили придумать новое. Ну ладно.

Идея-то понятна, хотя меня больше интересует почему именно такое решение.
Впрочем деваться нам некуда, будем работать с тем что они напридумали.

WatchCat ★★★★★
()
Ответ на: комментарий от monk

Так здесь то же самое: Content-Location: /contacts/stored-results/17

Мне показалось это самой мутной частью всей затеи. Т.е. добавить QUERY выглядит разумным, но конкретные паттерны для работы с кешами и прочим стейтом лучше бы предложили отдельно.

Lucky ★★
()
Ответ на: комментарий от Lucky

А как иначе? Если даже считать, что можно проксировать GET с параметрами (хотя когда-то достаточно было «?» в адрес добавить, чтобы прокси не мешал), то для QUERY параметры это всё тело, которое может несколько мегабайтов быть (иначе был бы GET).

Поэтому существенным остаётся только: чтобы POST не использовали не по назначению.

monk ★★★★★
()
Ответ на: комментарий от monk

В базах даных используются разные паттерны доступа к результатам запроса: свежий результат на каждый запрос, материализованные представления, один проход через курсор и т.п. Впрочем, среди авторов представители Akamai и Cloudflare - они наверняка уже обо всем подумали.

Lucky ★★
()

Когда стоит ждать его добавления в основные браузеры и curl?

question4 ★★★★★
()
Ответ на: комментарий от gns

Потом оставят только QUERY, а GET и POST (и остальное) выкинут!

aboite
()

Есть вариант, что это подхватят как замена GET, и все сайты станут просто доменными и безссылочными, как веб приложения, тупо тело в <body>...</body> менять будут и всё. Даже ссылкой на смешную пикчу не поделишься, как добираться до неё надо будет рассказывать так же как сейчас описывают путь до пункта меню в настройках мол иди на сайт ляляля.экхемпле.ком третья кнопка слева, в первой колонке, в подгрузившейся странице вторая ссылка снизу и там смешная кися! а там сися

Короче в наихудшем варианте развития, вместе с чуть более удобной плюшкой в комплекте идёт катастрофический по последствиям удар по гипертексту и вебу в целом, в его классическом понимании. Возможно это инициатива связанная с нейроскрапом и постепенным уходом поисковиков от модели выдачи ссылок на сайты.

LINUX-ORG-RU ★★★★★
()
Последнее исправление: LINUX-ORG-RU (всего исправлений: 1)
Ответ на: комментарий от LINUX-ORG-RU

Так веб-приложения уже есть. Хуже не будет. А ссылки в том виде, как на сообщение на этом форуме, никто не мешает делать. Разве что будут писать не https://www.linux.org.ru/news/internet/18322124?cid=18323813, а https://www.linux.org.ru/news/internet/18322124/cid/18323813.

monk ★★★★★
()
Последнее исправление: monk (всего исправлений: 1)
Ответ на: комментарий от monk

QUERY позволит все GET запросы вида

  • https://www.linux.org.ru/news/internet/18322124?cid=18323813

Превратить в запросы вида

  • https://www.linux.org.ru/call

А данные в POST тело уйдут и никаких путей вида

  • /news/internet/18322124/cid/18323813

не будет, они будут в виде POST тела в виде

  • section=news&subsection=internet&tid=18322124&cid=18323813

При наведении мышки в браузере на любую ссылку, ссылка будет одинаковой.


Это я исходя из варианта злоупотребления QUERY вместо GET, а оно будет. Вопрос лишь в том, в некоторых местах, или очень много где, ибо достаточно этому быть внедрено по умолчанию в тот или иной фреймворк и по закону уточки кря кря, оно резко станет массово распространено.

Так веб-приложения уже есть.

Вопрос не в том что есть, а чего нет, а в условиях и среды наличия чего либо, когда они склоняют пласты масс как разработчиков так и пользователей к чему-то. Динамика, тенденция и так далее.

Однажды кто-то в полушутку придумал сервера на js писать, на то время было ржамба и гыгыгы, а спустя пару лет, серьёзные дяди вещали с трибун о продакшоне, а потом появился тайпскрипт, как героическое решение искусственно созданных проблем.

Если будет что-то хорошо, оно просто будет, есть смысл прикидывать то что будет плохо =) Ну новая фича и новая фича, в ней проблемы нет, но она может помогать делать то что проблемой будет.
Не для разработчиков, а пользователей. Для меня как ну с натяжкой разработчика, фича прикольная, а как для пользователя абсолютно бесполезная и скорее вредная ибо цель QUERY заменять если не везде, то много где GET, тоесть абсолютные ссылки, тоесть гипертекст, тоесть возможность прямолинейно ссылаться и так далее.

Вотъ [по мотивам, белка истеричка, если так удобнее =) ]

LINUX-ORG-RU ★★★★★
()
Последнее исправление: LINUX-ORG-RU (всего исправлений: 1)
Ответ на: комментарий от LINUX-ORG-RU

При наведении мышки в браузере на любую ссылку, ссылка будет одинаковой.

Так QUERY через ссылку не пробросить. Нужен или FORM или JS.

monk ★★★★★
()
Ответ на: комментарий от monk

Пока что да, то и странно, в текущем состоянии это тупо дубль POST с мелкими различиями, так что ждём новую HTML спеку, с расширенным тегом <a> или его спец версией. =)

Увидим, просто обозначили в треде и теоретические плюсы и минусы и предвкушения и опасения и намана

LINUX-ORG-RU ★★★★★
()
Ответ на: комментарий от LINUX-ORG-RU

так что ждём новую HTML спеку, с расширенным тегом или его спец версией

Тогда ссылки с QUERY станут рабочими, так как в этом тэге как-то будет записана ссылка.

Теоретически можно по аналогии с IMG в href писать base64 от тела.

monk ★★★★★
()
Ответ на: комментарий от aeroflot

В REST приложении куча запросов на получения списков с фильтрами, которые хочется передавать как JSON

Простите, а что мешает Вам делать примерно так:

    $ch = curl_init($url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($params));
    $res = curl_exec($ch);

??

Psilocybe ★★★★★
()
Ответ на: комментарий от maxcom

Хреновая идея, потому что у запроса GET по RFC внезапно может быть body и никакой QUERY тут не нужен.

RAtioNAn
()
Ответ на: комментарий от monk

по аналогии с IMG в href писать base64 от тела

Нет, надо дополнительно к элементам A и FORM
сделать элемент Q, в тело которого и помещать текст запроса.
Это позволит формировать страницы запросами к ИИ.

Saakx
()
Ответ на: комментарий от maxcom

Шшш>>А не проще ли было просто узаконить передачу параметров в теле запроса для GET?

Это и сейчас можно, стандарт не запрещает.

Теоретически можно, но никто не гарантирует, что мой нестандартный GET с телом будет работать в любом окружении. В стандарте ведь этого нет, а значит, реализации серверов/прокси/сторонних API/… не обязаны поддерживать GET с телом. И некоторые наверняка не будут.

Nervous ★★★★★
()
Последнее исправление: Nervous (всего исправлений: 1)
Ответ на: комментарий от Nervous

Теоретически можно,

В стандарте ведь этого нет,

Наоборот. В стандарте это как раз есть, а на практике API библиотек реализующих HTTP-клиента часто не поддерживает установку тела запроса с GET’ом , начиная прямо с браузера:

https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch

Setting a body

The request body is the payload of the request: it’s the thing the client is sending to the server. You cannot include a body with GET requests, …

r--r--r--
()
Ответ на: комментарий от aeroflot

С другой стороны нужна поддержка readonly impersonation для админа, где запрещаем все запросы кроме GET с auth token юзера под которым мы заходим.

Так если запрещено всё кроме GET, то зачем нужно? Чтобы вместо «запрещён POST» получить «запрещён QUERY»?

monk ★★★★★
()
Ответ на: комментарий от monk

Стандартизуют, допустим, поле данных с шифром ресурса шифр_юникодом->json; будет вместо url в GET. Браузеры будут копировать этот код неявно, но вместе с ссылкой/адресом сайта. Впоследствии это тоже стандартизуют. Получим скрытый канал чего угодно в обход ведома пользователя.

aboite
()
Для того чтобы оставить комментарий войдите или зарегистрируйтесь.