HTTP POST с параметрами запроса URL - хорошая идея или нет?

Я разрабатываю API для перехода по HTTP, и мне интересно, если использовать команду HTTP POST, но только с параметрами запроса URL и без тела запроса, это хороший способ.

Вопросы:

  • "Хороший веб-дизайн" требует, чтобы не-идемпотентные действия отправлялись через POST. Это не-идемпотентное действие.
  • Легче разрабатывать и отлаживать это приложение, когда параметры запроса присутствуют в URL-адресе.
  • API не предназначен для широкого использования.
  • Кажется, что сделать запрос POST без тела займет немного больше работы, например. a Content-Length: 0 должен быть явно добавлен.
  • Мне также кажется, что POST без тела немного противоречит ожиданиям разработчиков и HTTP-фреймворков.

Есть ли еще недостатки или преимущества для отправки параметров в запрос POST через URL-запрос, а не в тело запроса?

Изменить: причина этого в том, что операции не являются идемпотентными и имеют побочные эффекты, кроме поиска. См. спецификацию HTTP:

В частности, конвенция была что GET и HEAD методы НЕ ДОЛЖНЫ значимость принятия другого чем поиск. Эти методы должны считаться "безопасным". Это позволяет пользователю агенты для представления других методов, таких как POST, PUT и DELETE, в особым образом, чтобы пользователь был создан осознавая тот факт, что возможно запрашивается небезопасное действие.

...

Методы могут также обладать свойством "идемпотентность" в этом (кроме ошибки или срока действия) побочные эффекты N > 0 одинаковы запросы такие же, как для одного запрос. Методы GET, HEAD, PUT и DELETE делятся этим свойством. Также, методы ВАРИАНТЫ и ТРАСЕ СЛЕДУЕТ НЕ имеют побочных эффектов, и поэтому по сути, идемпотент.

Ответы

Ответ 1

Если ваше действие не является идемпотентным, то вы ДОЛЖНЫ использовать POST. Если вы этого не сделаете, вы просто просите о беде. GET, PUT и DELETE должны быть идемпотентны. Представьте, что произойдет в вашем приложении, если клиент предварительно запросил все возможные запросы GET для вашей службы - если это вызовет видимые для клиента побочные эффекты, то что-то не так.

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

Подумайте о части запроса URL-адреса в качестве команды ресурса, чтобы ограничить область текущего запроса. Как правило, строки запроса используются для сортировки или фильтрации запроса GET (например, ?page=1&sort=title), но я полагаю, что имеет смысл в POST также ограничить область действия (возможно, как ?action=delete&id=5).

Ответ 2

Все правы: придерживайтесь POST для не-идемпотентных запросов.

Как использовать и строку запроса запроса URI, и содержимое запроса? Ну, это действительно HTTP (см. Примечание 1), так почему бы и нет!

Это также совершенно логично: URL-адреса, включая их часть строки запроса, предназначены для поиска ресурсов. В то время как глаголы HTTP-метода (POST - и его дополнительный контент запроса) предназначены для указания действий или того, что делать с ресурсами. Это должны быть ортогональные проблемы. (Но они не являются красиво ортогональными проблемами для специального случая ContentType = application/x-www-form-urlencoded, см. Примечание 2 ниже.)

Примечание 1: Спецификация HTTP (1.1) не указывает, что параметры запроса и контент являются взаимоисключающими для HTTP-сервера, который принимает запросы POST или PUT. Таким образом, любой сервер может принять оба. То есть если вы пишете сервер, вам нечего мешать принимать (и, возможно, негибкую структуру). Как правило, сервер может интерпретировать строки запросов в соответствии с любыми правилами, которые он хочет. Он может даже интерпретировать их с условной логикой, которая также относится к другим заголовкам, таким как Content-Type, что приводит к примечанию 2:

Примечание 2: если веб-браузер является основным способом доступа пользователей к вашему веб-приложению, а application/x-www-form-urlencoded - это тип контента, который они публикуют, то вы должны следуйте правилам этого Content-Type. И правила для application/x-www-form-urlencoded гораздо более специфичны (и, откровенно говоря, необычны): в этом случае вы должны интерпретировать URI как набор параметров, а не местоположение ресурса. [Это та же самая точка полезности, которую поднял Властелин; что может быть сложно использовать веб-формы для контента POST на вашем сервере. Просто объяснил немного по-другому.]

Примечание 3: для чего нужны строки запроса? RFC 3986 определяет строки HTTP-запросов как часть URI, которая работает как неиерархический способ поиска ресурса.

В случае, если читатели, задающие этот вопрос, хотят спросить, какая хорошая архитектура RESTful: шаблон архитектуры RESTful не требует, чтобы схемы URI работали определенным образом. Архитектура RESTful относится к другим свойствам системы, таким как кешируемость ресурсов, дизайн самих ресурсов (их поведение, возможности и представления) и удовлетворяет ли идемпотенция. Или, другими словами, достижение дизайна, который очень совместим с протоколом HTTP и его набором глаголов метода HTTP.:-) (Другими словами, архитектура RESTful не очень предсказуема с расположением ресурсов.)

Заключительное примечание: иногда параметры запроса используются для других вещей, которые не являются ни локализацией ресурсов, ни кодированием контента. Когда-либо видели параметр запроса, например "PUT = true" или "POST = true"? Это обходные пути для браузеров, которые не позволяют использовать методы PUT и POST. Хотя такие параметры рассматриваются как часть строки запроса URL (на проводнике), я утверждаю, что они не являются частью URL-запроса по духу.

Ответ 3

Вам нужны причины? Здесь один:

Веб-форму нельзя использовать для отправки запроса на страницу, использующую сочетание GET и POST. Если вы установите метод формы в GET, все параметры находятся в строке запроса. Если вы установите метод формы POST, все параметры находятся в теле запроса.

Источник: стандарт HTML 4.01, раздел 17.13 Представление формы

Ответ 4

С программной точки зрения, для клиента он упаковывает параметры и добавляет их на url и проводит POST против GET. На стороне сервера он оценивает входящие параметры из запроса, а не отправленные байты. В принципе, это стирка.

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

Тем не менее, с точки зрения программиста, я предпочитаю разрешать либо POST со всеми параметрами в теле, либо GET со всеми параметрами на url, и явно игнорировать параметры url с любым запросом POST. Это позволяет избежать путаницы.

Ответ 5

Я бы подумал, что все еще может быть довольно RESTful иметь аргументы запроса, которые идентифицируют ресурс в URL-адресе, сохраняя при этом полезную нагрузку контента, ограниченную телом POST. Казалось бы, это отделяет соображения "Что я посылаю?" против "Кто я его отправлю?".

Ответ 6

В лагере REST есть некоторые руководящие принципы, которые мы можем использовать для стандартизации способа использования HTTP-глаголов. Это полезно при создании API RESTful, как вы это делаете.

В двух словах: GET должен быть доступен только для чтения, т.е. Не влияет на состояние сервера. POST используется для создания ресурса на сервере. PUT используется для обновления или создания ресурса. DELETE используется для удаления ресурса.

Другими словами, если ваше действие API изменяет состояние сервера, REST советует нам использовать POST/PUT/DELETE, но не GET.

Пользовательские агенты обычно понимают, что выполнение нескольких POST файлов является плохим и будет предупреждать об этом, поскольку целью POST является изменение состояния сервера (например, оплата товаров в кассе), и вы, вероятно, не хотите делать это дважды

Сравните с GET, который вы можете делать часто, как вам нравится (idempotent).

Ответ 7

Я согласен - возможно, безопаснее использовать GET-запрос, если вы просто передаете данные по URL-адресу, а не в теле. См. этот аналогичный вопрос для некоторых дополнительных представлений по всей концепции POST + GET.