2009-03-04 2 views
328

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

соображение:

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

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

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

В частности, соглашение было установлено, что GET и ГОЛОВА методов не должен иметь значения принимает меры другого , чем извлечение. Эти методы должны быть считаться «безопасными». Это позволяет пользователям агентам представлять другие способы, , такие как POST, PUT и DELETE, в специальном режиме , так что пользователь получает , осознавая тот факт, что запрашивается возможное опасное действие, возможно, .

...

Методы могут также обладать свойством «идемпотентности» в том, что (кроме вопросов ошибок или истечения срока действия) в побочных эффектов N> 0 идентичных запросов такого же, как для один запрос . Методы GET, HEAD, PUT и DELETE делятся этим свойством. Кроме того, методы OPTIONS и TRACE SHOULD НЕ имеют побочных эффектов, а также неотъемлемо идемпотент.

+6

Зачем использовать POST вообще, если вы не собираетесь предоставлять данные в теле? –

+78

Поскольку операция не является идемпотентной. –

+1

Что вы пытаетесь сделать, это не идемпотент, а не настоящий POST? Кажется, что либо ваш дизайн REST имеет некоторые проблемы, либо взаимодействие, которое вы пытаетесь создать, не поддается интерфейсу RESTful. Возможно, мы сможем помочь вам сформулировать лучший интерфейс REST, если вы дадите более подробную информацию. – Jared

ответ

173

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

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

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

+1

Я выбрал этот ответ для этого конкретного случая, но я думаю, что аргумент Р.Бемроуза привлекателен для публичных API. –

+1

Я не думаю, что его ответ строго правильный. Если вам известны параметры URL для вашего сообщения формы, когда HTML-страница отправляется клиенту, вы можете привязать эти параметры URL к атрибуту действия формы, иначе JavaScript может установить параметры URL-адреса при отправке формы. –

+2

Как насчет сообщения xml-файла на URL-адрес с параметрами запроса? это возможно? – holaSenor

8

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

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

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

-9

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

+13

Если операция имеет побочные эффекты, то, безусловно, не «безопаснее» использовать метод GET, потому что браузер предполагает, что все GET являются идемпотентными. – dcstraw

56

Вам нужны причины? Вот один из них:

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

Источник: HTML стандарт 4,01, раздел 17.13 Form Submission

+7

Это достойный аргумент, но я думаю, что современные реализации Javascript в браузере делают его спорным. Я подумаю об этом, но это убедительно выглядит в будущем. Просто потому, что я не использую форму для этого сейчас, это не значит, что я не захочу позже. –

+7

Смешивание GET с POST - это просто плохая идея - ужасно нарушение HTTP и без уважительной причины. – aehlke

+4

Этот сниппет не отображается на странице, которую вы связали с – Gareth

2

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

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

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

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

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

+10

В лагере REST вам следует использовать HTTP, как определено в спецификации HTTP. т. е. RFC2616 Ничего больше, не меньше. –

+1

@Darrel Ссылаясь на https://www.ibm.com/developerworks/webservices/library/ws-restful/: REST просит разработчиков использовать HTTP-методы явно и в соответствии с определением протокола. Этот базовый принцип проектирования REST устанавливает взаимно однозначное сопоставление между операциями создания, чтения, обновления и удаления (CRUD) и методов HTTP. Согласно этому сопоставлению: Чтобы создать ресурс на сервере, используйте POST. Чтобы получить ресурс, используйте GET. Чтобы изменить состояние ресурса или обновить его, используйте PUT. Чтобы удалить или удалить ресурс, используйте DELETE. – saille

+5

Извините, но это просто неправильно. REST требует соблюдения однородного интерфейса. Если вы используете HTTP, то этот унифицированный интерфейс частично определяется RFC 2616. В этой спецификации нет сопоставления «один-к-одному» между созданием, чтением, обновлением и удалением и методами HTTP. –

85

Все правы: придерживайтесь 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 архитектура не очень presciptive с тем, как ресурсы расположены.)

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

4

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

+5

Вопрос был не в REST. –

+2

@ user359996 Не все HTTP-API являются RESTful. Фактически, большинство API, которые утверждают, что на самом деле это не так. Кроме того, забавный факт, REST также не является HTTP-. –

Смежные вопросы