PUT против POST в REST

Согласно спецификации HTTP/1.1 Spec:

Метод POST используется для запроса, чтобы исходный сервер принял объект, заключенный в запросе, в качестве нового подчиненного ресурса, идентифицированного Request-URI в Request-Line

Другими словами, POST используется для создания.

Метод PUT запрашивает, чтобы закрытый объект хранился в поставляемом Request-URI. Если Request-URI относится к уже существующему ресурсу, закрытое сущность СЛЕДУЕТ считаться измененной версией той, которая находится на сервере происхождения. Если Request-URI не указывает на существующий ресурс и что URI может быть определен как новый ресурс запрашивающим пользовательским агентом, исходный сервер может создать ресурс с этим URI. "

То есть PUT используется для создания или обновления.

Итак, какой из них следует использовать для создания ресурса? Или нужно поддерживать оба?

+5153
источник поделиться
36 ответов
  • 1
  • 2

В целом:

Для создания могут использоваться как PUT, так и POST.

Вы должны спросить: для чего вы выполняете действие? чтобы отличить то, что вы должны использовать. Предположим, вы разрабатываете API для вопросов. Если вы хотите использовать POST, вы должны сделать это в списке вопросов. Если вы хотите использовать PUT, вы можете сделать это по конкретному вопросу.

Можно использовать оба варианта, поэтому я должен использовать его в дизайне RESTful:

Вам не нужно поддерживать PUT и POST.

Используется для вас. Но просто не забудьте использовать правильный вариант в зависимости от того, на каком объекте вы ссылаетесь в запросе.

Некоторые соображения:

  • Вы называете объекты URL-адресов, которые вы создаете явно, или разрешаете серверу? Если вы их назовете, используйте PUT. Если вы разрешите серверу, то используйте POST.
  • PUT является идемпотентным, поэтому, если вы дважды нажмете объект, это не будет иметь никакого эффекта. Это приятное свойство, поэтому я мог бы использовать PUT, когда это возможно.
  • Вы можете обновить или создать ресурс с помощью PUT с тем же URL-адресом объекта
  • С помощью POST вы можете одновременно внести 2 запроса, внося изменения в URL-адрес, и они могут обновлять разные части объекта.

Пример:

Я написал следующее как часть другого ответа на SO относительно этого:

POST

Используется для изменения и обновления ресурса

POST /questions/<existing_question> HTTP/1.1
Host: www.example.com/

Обратите внимание, что следующая ошибка:

POST /questions/<new_question> HTTP/1.1
Host: www.example.com/

Если URL еще не создан, вы не должен использовать POST для его создания указывая имя. Это должно привести к ошибке "ресурс не найден" потому что <new_question> не существует все же. Вы должны нажать кнопку <new_question>ресурс на сервере.

Вы могли бы сделать что-то вроде это для создания ресурсов с помощью POST:

POST /questions HTTP/1.1
Host: www.example.com/

Обратите внимание, что в этом случае ресурс имя не указано, новые объекты URL-адрес будет возвращен вам.

PUT:

Используется для создания ресурса или перезапишите его. Пока вы указываете ресурсов новый URL.

Для нового ресурса:

PUT /questions/<new_question> HTTP/1.1
Host: www.example.com/

Чтобы перезаписать существующий ресурс:

PUT /questions/<existing_question> HTTP/1.1
Host: www.example.com/
+4066
источник

Вы можете найти утверждения в Интернете, которые говорят

Ничего не получается.


Лучше выбрать между PUT и POST на основе idempotence действия.

PUT подразумевает помещение ресурса - полностью заменяя все, что доступно по данному URL, с другой. По определению, PUT является идемпотентным. Сделайте это столько раз, сколько хотите, и результат будет таким же. x=5 является идемпотентным. Вы можете указать ресурс, существовавший ранее или нет (например, для создания или для обновления)!

POST обновляет ресурс, добавляет вспомогательный ресурс или вызывает изменение. POST не является идемпотентным, так как x++ не является идемпотентным.


По этому аргументу PUT предназначен для создания, когда вы знаете URL-адрес создаваемой вещи. POST можно использовать для создания, когда вы знаете URL-адрес "factory" или менеджера для категории вещей, которые вы хотите создать.

так:

POST /expense-report

или

PUT  /expense-report/10929
+2129
источник
  • POST для URL-адреса создает дочерний ресурс по URL-адресу, определенному сервером.
  • PUT to URL создает/заменяет ресурс целиком по указанному клиентом URL.
  • PATCH to URL обновляет часть ресурса по указанному клиенту URL.

Соответствующая спецификация для PUT и POST - RFC 2616 §9.5ff.

POST создает дочерний ресурс, поэтому POST для /items создает ресурсы, которые находятся под ресурсом /items. Например. /items/1. Отправка одного и того же почтового пакета дважды создаст два ресурса.

PUT предназначен для создания или замены ресурса по URL-адресу, известному клиенту.

Следовательно: PUT является только кандидатом на CREATE, где клиент уже знает URL-адрес до создания ресурса. Например. /blogs/nigel/entry/when_to_use_post_vs_put в качестве заголовка используется в качестве ключа ресурса

PUT заменяет ресурс по известному URL, если он уже существует, поэтому отправка одного и того же запроса дважды не имеет никакого эффекта. Другими словами, вызовы PUT являются идемпотентными.

RFC звучит так:

Принципиальное различие между запросами POST и PUT отражается в различном значении Request-URI. URI в запросе POST идентифицирует ресурс, который будет обрабатывать вложенную сущность. Этот ресурс может быть процессом приема данных, шлюзом к другому протоколу или отдельным объектом, принимающим аннотации. Напротив, URI в запросе PUT идентифицирует объект, заключенный в запросе - пользовательский агент знает, для чего предназначен URI, и сервер НЕ ДОЛЖЕН пытаться применить запрос к какому-либо другому ресурсу. Если сервер желает, чтобы запрос был применен к другому URI,

Примечание: PUT в основном использовался для обновления ресурсов (путем их полной замены), но в последнее время наблюдается движение к использованию PATCH для обновления существующих ресурсов, поскольку PUT указывает, что он заменяет весь ресурс. RFC 5789.

Обновление 2018: есть случай, который можно избежать, чтобы избежать PUT. Смотрите "ОТДЫХ без ПУТА"

С техникой "REST без PUT" идея заключается в том, что потребители вынуждены публиковать новые "несущественные" ресурсы запросов. Как обсуждалось ранее, изменение почтового адреса клиента - это POST для нового ресурса "ChangeOfAddress", а не PUT ресурса "Customer" с другим значением поля почтового адреса.

взято из REST API Design - Моделирование ресурсов Пракашем Субраманиамом из Thoughtworks

Это вынуждает API избегать проблем с переходом состояний при обновлении одного ресурса несколькими клиентами и более точно согласуется с источником событий и CQRS. Когда работа выполняется асинхронно, размещение POST и ожидание его применения кажется подходящим.

+677
источник

Резюме:

Создать:

Может выполняться с PUT или POST следующим образом:

PUT

Создает новый ресурс с newResourceId в качестве идентификатора в /URI ресурсов или коллекции.

PUT /resources/<newResourceId> HTTP/1.1 

POST

Создает новый ресурс A в URI ресурсов/или коллекция. Обычно идентификатор возвращается сервером.

POST /resources HTTP/1.1

Обновление:

Можно выполнить только с помощью PUT следующим образом:

PUT

Обновляет ресурс с помощью существующегоResourceId как идентификатора, в /URI ресурсов или коллекции.

PUT /resources/<existingResourceId> HTTP/1.1

Пояснение:

При работе с REST и URI как общим, у вас есть общий слева и определенный справа. generics обычно называются коллекциями, и более конкретные элементы можно назвать ресурсом. Обратите внимание, что ресурс может содержать коллекцию.

Примеры:

< - generic - specific →

URI: website.com/users/john
website.com  - whole site
users        - collection of users
john         - item of the collection, or a resource

URI:website.com/users/john/posts/23
website.com  - whole site
users        - collection of users
john         - item of the collection, or a resource
posts        - collection of posts from john
23           - post from john with identifier 23, also a resource

Когда вы используете POST, вы всегда ссылаетесь на коллекцию, поэтому, когда вы говорите:

POST /users HTTP/1.1

вы отправляете нового пользователя пользователям коллекция.

Если вы продолжаете и попробуйте что-то вроде этого:

POST /users/john HTTP/1.1

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

Как только вы используете PUT, вы ссылаетесь на ресурс или отдельный элемент, возможно, внутри коллекции. Поэтому, когда вы говорите:

PUT /users/john HTTP/1.1

вы сообщаете об обновлении сервера или создаете, если он не существует, ресурс john под пользовательской коллекцией.

Spec:

Позвольте мне выделить некоторые важные части спецификации:

POST

Метод POST используется для запроса, чтобы исходный сервер принял объект, заключенный в запрос, в качестве нового подчиненного идентифицированного ресурса по запросу-URI в строке запроса

Следовательно, создается новый ресурс в коллекции .

PUT

Метод PUT запрашивает, что закрытый объект хранится в поставляемом Request-URI. Если Request-URI ссылается на ресурс уже существующий, закрытая сущность СЛЕДУЕТ считаться измененной версией той, которая находится на исходном сервере. Если Request-URI делает не ссылкой на существующий ресурс, а этот URI способен определяться как новый ресурс запрашивающим пользователем агент, исходный сервер может создать ресурс с этим URI. "

Следовательно, создайте или обновите на основе существования ресурса.

Справка:

+208
источник

Я хотел бы добавить свой "прагматичный" совет. Используйте PUT, когда вы знаете "id", с помощью которого можно сохранить объект, который вы сохраняете. Использование PUT не будет работать слишком хорошо, если вам понадобится, скажем, идентификатор, сгенерированный с помощью базы данных, который будет возвращен вам для будущих поисков или обновлений.

Итак: для сохранения существующего пользователя или того, где клиент генерирует идентификатор, и было проверено, что идентификатор уникален:

PUT /user/12345 HTTP/1.1  <-- create the user providing the id 12345
Host: mydomain.com

GET /user/12345 HTTP/1.1  <-- return that user
Host: mydomain.com

В противном случае используйте POST для первоначального создания объекта и PUT для обновления объекта:

POST /user HTTP/1.1   <--- create the user, server returns 12345
Host: mydomain.com

PUT /user/12345 HTTP/1.1  <--- update the user
Host: mydomain.com
+170
источник

POST означает "создать новый", как в "Вот вход для создания пользователя, создайте его для меня".

PUT означает "вставить, заменить, если уже существует", как в "Вот данные для пользователя 5".

Вы используете POST для example.com/users, так как вы еще не знаете URL-адреса пользователя, вы хотите, чтобы сервер его создал.

Вы PUT на example.com/users/id, так как хотите заменить/создать конкретного пользователя.

POSTing дважды с теми же данными означает создание двух одинаковых пользователей с разными идентификаторами. Дважды запуска с теми же данными создает пользователя первым и обновляет его до того же состояния во второй раз (без изменений). Поскольку вы оказываетесь в том же состоянии после PUT, независимо от того, сколько раз вы его выполняете, он считается "одинаково мощным" каждый раз - идемпотент. Это полезно для автоматического повторения запросов. Не больше "вы уверены, что хотите отправить", когда вы нажимаете кнопку "Назад" в браузере.

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

+165
источник

Используйте POST для создания и PUT для обновления. Все равно, как Ruby on Rails делает это.

PUT    /items/1      #=> update
POST   /items        #=> create
+123
источник

Оба используются для передачи данных между клиентом и сервером, но между ними есть тонкие различия:

Enter image description here

Аналогия:

  • PUT т.е. возьми и положи, где это было.
  • POST как отправить почту в почтовом отделении.

enter image description here

Социальная сеть/Сетевая аналогия:

  • Публикация в социальных сетях: когда мы публикуем сообщение, создается новое сообщение.
  • Поставьте (т.е. отредактируйте) сообщение, которое мы уже опубликовали.
+112
источник

REST - это концепция очень высокого уровня. На самом деле, он даже не упоминает HTTP вообще!

Если у вас есть какие-либо сомнения относительно того, как реализовать REST в HTTP, вы всегда можете взглянуть на спецификацию протокола публикации Atom (AtomPub). AtomPub - это стандарт для написания веб-сервисов RESTful с HTTP, который был разработан многими светилами HTTP и REST при участии Роя Филдинга, изобретателя REST и (co-) самого HTTP.

На самом деле, вы даже можете использовать AtomPub напрямую. Хотя он и вышел из сообщества блогеров, он никоим образом не ограничен блогами: это общий протокол для RESTful взаимодействия с произвольными (вложенными) коллекциями произвольных ресурсов через HTTP. Если вы можете представить свое приложение как вложенную коллекцию ресурсов, то вы можете просто использовать AtomPub и не беспокоиться о том, использовать ли PUT или POST, какие коды состояния HTTP возвращать и все эти подробности.

Вот что AtomPub говорит о создании ресурса (раздел 9.2):

Чтобы добавить участников в коллекцию, клиенты отправляют запросы POST на URI коллекции.

+65
источник

Решение о том, следует ли использовать PUT или POST для создания ресурса на сервере с HTTP + REST API, основывается на том, кому принадлежит структура URL. Наличие клиента или участие в определении, структура URL является ненужной связью, аналогичной нежелательным связям, которые возникли из SOA. Избежание типов муфт является причиной того, что REST настолько популярен. Поэтому правильный метод для использования - POST. Есть исключения из этого правила, и они возникают, когда клиент хочет сохранить контроль над структурой местоположения ресурсов, которые он развертывает. Это редкость и, вероятно, означает, что что-то еще не так.

В этот момент некоторые люди будут утверждать, что если используются URL RESTful, клиент знает URL-адрес ресурса, и поэтому PUT является приемлемым. В конце концов, именно поэтому канонические, нормализованные, Ruby on Rails, URL-адреса Django важны, посмотрите на API Twitter... бла-бла-бла. Этим людям нужно понимать нет такой вещи, как Restful-URL, и что сам Рой Филдинг утверждает, что:

API REST не должен определять фиксированные имена ресурсов или иерархии ( очевидная связь клиента и сервера). Серверы должны иметь свободу для управления собственным пространством имен. Вместо этого разрешите серверам инструктировать клиенты о том, как создавать соответствующие URI, например, в HTML форм и шаблонов URI, определяя эти инструкции в среде типов и связей. [Неспособность здесь подразумевает, что клиенты предполагая структуру ресурсов из-за внеполосной информации, такой как специфический для домена стандарт, который является ориентированным на данные эквивалентом Функциональная связь RPC].

http://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertext-driven

Идея URL-адреса RESTful на самом деле является нарушением REST, поскольку сервер отвечает за структуру URL-адреса и должен иметь право решать, как использовать его, чтобы избежать связи. Если это смущает вас, прочитайте о значении самообнаружения в дизайне API.

Использование POST для создания ресурсов связано с соображениями дизайна, потому что POST не является идемпотентным. Это означает, что повторение POST несколько раз не гарантирует одинаковое поведение каждый раз. Это пугает людей от использования PUT для создания ресурсов, когда им этого не нужно. Они знают это неправильно (POST для CREATE), но они все равно делают, потому что они не знают, как решить эту проблему. Эта проблема проявляется в следующей ситуации:

  • Клиент отправляет новый сервер на сервер.
  • Сервер обрабатывает запрос и отправляет ответ.
  • Клиент никогда не получает ответ.
  • Сервер не знает, что клиент не получил ответа.
  • У клиента нет URL-адреса ресурса (поэтому PUT не является опцией) и повторяет POST.
  • POST не является идемпотентным, а сервер...

Шаг 6 - это то, где люди часто путаются о том, что делать. Тем не менее, нет оснований для создания kludge для решения этой проблемы. Вместо этого HTTP может использоваться как указано в RFC 2616, и сервер отвечает:

10.4.10 409 Конфликт

Запрос не может быть выполнен из-за конфликта с текущим состояние ресурса. Этот код разрешен только в ситуациях, когда ожидается, что пользователь сможет разрешить конфликт и повторно отправьте запрос. Тело ответа ДОЛЖНО включать достаточно

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

Конфликты чаще всего возникают в ответ на запрос PUT. Для например, если использовалось управление версиями, а объект PUT включали изменения в ресурс, который противоречит ранее (сторонний) запрос, сервер может использовать ответ 409 чтобы указать, что он не может выполнить запрос. В этом случае вероятно, будет содержать список различий между две версии в формате, определяемом ответом Content-Type.

Ответ с кодом состояния 409 Конфликт - это правильный регресс, потому что:

  • Выполнение POST данных, которое имеет идентификатор, который соответствует ресурсу, уже находящемуся в системе, является "конфликтом с текущим состоянием ресурса".
  • Поскольку важная часть заключается в том, что клиент понимает, что сервер имеет свой ресурс и предпринимает соответствующие действия. Это "ситуация (ситуации), когда ожидается, что пользователь сможет разрешить конфликт и повторно отправить запрос".
  • Ответ, который содержит URL-адрес ресурса с конфликтующим идентификатором и соответствующими предварительными условиями для ресурса, предоставит "достаточную информацию для пользователя или агента пользователя для устранения проблемы", что является идеальным случаем для RFC 2616.

Обновление, основанное на выпуске RFC 7231 для замены 2616

RFC 7231 предназначен для замены 2616 и Раздел 4.3.3 описывает возможный ответ для POST

Если результат обработки POST будет эквивалентен представление существующего ресурса, исходный сервер МОЖЕТ перенаправлять пользовательский агент к этому ресурсу, отправив ответ 303 (см. раздел "Другие" ) с существующим идентификатором ресурса в поле "Место". Эта имеет преимущества предоставления пользовательскому агенту идентификатора ресурса и передачу представления посредством метода, более поддающегося общее кэширование, но за счет дополнительного запроса, если пользователь агент еще не кэширован.

Теперь может возникнуть соблазн просто вернуть 303 в случае повторения POST. Однако верно и обратное. Возвращение 303 будет иметь смысл только в том случае, если несколько запросов на создание (создание разных ресурсов) возвращают один и тот же контент. Примером может служить "спасибо за отправку вашего сообщения о запросе", что клиент не должен повторно загружать каждый раз. RFC 7231 по-прежнему сохраняет в разделе 4.2.2, что POST не должен быть идемпотентным и продолжает поддерживать, что POST должен использоваться для создания.

Для получения дополнительной информации об этом читайте article.

+60
источник

Мне нравится этот совет, из RFC 2616 определения PUT:

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

Это приводит к другому совету здесь, что PUT лучше всего применяется к ресурсам, которые уже имеют имя, а POST хорош для создания нового объекта под существующим ресурсом (и позволяя ему называть его имя).

Я интерпретирую это и требования идемпотентности в PUT, чтобы это означало, что:

  • POST хорош для создания новых объектов под коллекцией (и создавать не нужно идемпотент)
  • PUT хорош для обновления существующих объектов (и обновление должно быть идемпотентным).
  • POST также может использоваться для не-идемпотентных обновлений существующим объектам (особенно, изменяя часть объекта без указания всего этого - если вы думаете об этом, создание нового члена коллекции фактически является особым случаем этот вид обновления, с точки зрения коллекции)
  • PUT также может использоваться для создания, если и только если вы разрешаете клиенту указывать ресурс. Но поскольку клиенты REST не должны делать предположения о структуре URL, это меньше в намеченном духе вещей.
+53
источник

Короче:

PUT является idempotent, где состояние ресурса будет одинаковым, если одна и та же операция выполняется один или несколько раз.

POST не является idempotent, где состояние ресурса может стать другим, если операция выполняется несколько раз по сравнению с выполнением одного времени.

Аналогия с запросом базы данных

PUT. Вы можете думать о том же, что и "UPDATE STUDENT SET address =" abc ", где id =" 123 ";

POST Вы можете думать о чем-то вроде "INSERT INTO STUDENT (имя, адрес) VALUES (" abc "," xyzzz ");

Идентификатор студента автоматически генерируется.

С PUT, если один и тот же запрос выполняется несколько раз или один раз, состояние таблицы STUDENT остается неизменным.

В случае POST, если один и тот же запрос выполняется несколько раз, в базе данных создается несколько записей Студента, а состояние базы данных изменяется при каждом выполнении запроса "INSERT".

ПРИМЕЧАНИЕ. PUT нуждается в местоположении ресурса (уже-ресурсе), на котором должно произойти обновление, тогда как POST этого не требует. Поэтому интуитивно POST предназначен для создания нового ресурса, тогда как PUT необходим для обновления уже существующего ресурса.

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

+47
источник

POST - это как отправить письмо в почтовый ящик или отправить электронное письмо в очередь электронной почты. PUT похож на то, когда вы помещаете объект в кубическое отверстие или место на полке (у него есть известный адрес).

С помощью POST вы отправляете на адрес QUEUE или COLLECTION. С помощью PUT вы указываете адрес ITEM.

PUT является идемпотентным. Вы можете отправить запрос 100 раз, и это не имеет значения. POST не является идемпотентным. Если вы отправляете запрос 100 раз, вы получите 100 писем или 100 писем в почтовом ящике.

Общее правило: если вы знаете идентификатор или имя элемента, используйте PUT. Если вы хотите, чтобы идентификатор или имя элемента были назначены принимающей стороной, используйте POST.

POST versus PUT

+43
источник

Новый ответ (теперь, когда я лучше понимаю REST):

PUT - это просто утверждение о том, какое содержание, которое служба должна использовать с этого момента, для визуализации представлений ресурса, идентифицированного клиентом; POST - это выражение о том, какой контент должен предоставлять служба, с этого момента (возможно, дублируется), но до сервера, как идентифицировать этот контент.

PUT x (если x идентифицирует ресурс): "Замените содержимое ресурса, идентифицированного x моим содержимым".

PUT x (если x не идентифицирует ресурс): "Создайте новый ресурс, содержащий мой контент, и используйте x для его идентификации".

POST x: "Сохраните мой контент и дайте мне идентификатор, который я могу использовать для идентификации ресурса (старого или нового), содержащего указанный контент (возможно, смешанного с другим контентом). Указанный ресурс должен быть идентичным или подчиненным тому, который идентифицирует x ". "y ресурс подчинен x ресурсу", как правило, но не обязательно реализуется путем создания ya подпути x (например, x = /foo и y = /foo/bar) и изменения представления (ов) x ресурса, чтобы отразить существование новый ресурс, например, с гиперссылкой на ресурс y и некоторые метаданные. Только последний действительно необходим для хорошего дизайна, поскольку URL-адреса непрозрачны в REST - вы должны использовать гипермедиа вместо структуры URL-адреса на стороне клиента, чтобы в любом случае проходить службу.

В REST нет такой вещи, как ресурс, содержащий "контент". Я называю "контент" данными, которые служба использует для рендеринга представлений. Он обычно состоит из некоторых связанных строк в базе данных или файле (например, файл изображения). Это до службы для преобразования пользовательского контента во что-то, что может использовать служба, например, преобразование полезной нагрузки JSON в SQL-запросы.

Оригинальный ответ (может быть, легче читать):

PUT/something (если /something уже существует): "Возьмите все, что у вас есть /something и замените его тем, что я вам даю".

PUT/something (если /something еще не существует): "Возьми то, что я тебе даю, и поставлю его /something ".

POST/something: "Возьмите то, что я вам даю, и поставлю его в любом месте, где вы хотите /something пока вы дадите мне свой URL, когда закончите".

+39
источник

Короткий ответ:

Простое эмпирическое правило: используйте POST для создания, используйте PUT для обновления.

Длинный ответ:

POST:

  • POST используется для отправки данных на сервер.
  • Полезно, когда URL ресурса неизвестен

PUT

  • PUT используется для передачи состояния на сервер
  • Полезно, когда известен URL-адрес ресурса

Более длинный ответ:

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

С точки зрения архитектуры REST нет ничего важного. Мы могли бы жить без PUT. Но с точки зрения клиентского разработчика это сделало его жизнь намного проще.

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

+38
источник

Ruby on Rails 4.0 будет использовать метод PATCH вместо PUT для частичного обновления.

RFC 5789 говорит о PATCH (с 1995 года):

Для улучшения взаимодействия и предотвращения ошибок необходим новый метод. Метод PUT уже определен, чтобы перезаписать ресурс с полным новым телом и не может быть повторно использован для частичных изменений. В противном случае прокси и кэши, а также клиенты и серверы могут запутаться в результате операции. POST уже используется, но без широкой функциональной совместимости (например, нет стандартного способа обнаружения поддержки формата патча). PATCH упоминался в более ранних спецификациях HTTP, но не полностью определен.

" Edge Rails: PATCH - это новый первичный HTTP-метод для обновлений ", - объясняет он.

+36
источник

Рискуя повторить сказанное, важно помнить, что PUT подразумевает, что клиент контролирует, каким образом URL-адрес будет создан, когда создается ресурс. Таким образом, часть выбора между PUT и POST будет заключаться в том, насколько вы можете доверять клиенту для предоставления правильного, нормализованного URL-адреса, которые согласуются с тем,

Если вы не можете полностью доверять клиенту делать правильные вещи, это будет более целесообразно использовать POST для создания нового элемента, а затем отправить URL-адрес обратно клиенту в ответ.

+27
источник

В очень простой форме я беру пример временной шкалы Facebook.

Случай 1: Когда вы публикуете что-то на своей временной шкале, это новая новая запись. Поэтому в этом случае они используют метод POST, потому что метод POST не является идемпотентным.

Случай 2: Если ваш знакомый прокомментирует ваше сообщение в первый раз, это также создаст новую запись в базе данных, чтобы использовать метод POST.

Случай 3: если ваш друг редактирует свой комментарий, в этом случае у них есть идентификатор комментария, поэтому они будут обновлять существующий комментарий вместо создания новой записи в базе данных. Поэтому для этого типа операции используйте метод PUT, потому что он идемпотент. *

В одной строке используйте POST, чтобы добавить новую запись в базу данных и PUT в обновить что-то в базе данных.

+24
источник

Самое важное соображение - надежность. Если сообщение POST потеряно, состояние системы undefined. Автоматическое восстановление невозможно. Для сообщений PUT состояние undefined только до первой успешной попытки.

Например, не может быть хорошей идеей создавать транзакции с кредитными картами с помощью POST.

Если у вас есть автогенерированный URI на вашем ресурсе, вы все равно можете использовать PUT, передав клиенту сгенерированный URI (указывая на пустой ресурс).

Некоторые другие соображения:

  • POST аннулирует кешированные копии всего содержащего ресурса (улучшенная согласованность)
  • Ответы PUT не подлежат кэшированию, тогда как POST - это (Требовать контент-местоположение и срок действия)
  • PUT менее поддерживается, например. Java ME, старые браузеры, брандмауэры.
+21
источник

В дополнение к различиям, предложенным другими, я хочу добавить еще один.

В методе POST вы можете отправлять параметры тела в form-data

В методе PUT вам необходимо отправить параметры тела в x-www-form-urlencoded

Заголовок Content-Type:application/x-www-form-urlencoded

В соответствии с этим вы не можете отправлять файлы или multipart данные в методе PUT

РЕДАКТИРОВАТЬ

Тип контента "application/x-www-form-urlencoded" неэффективен для отправки больших количеств двоичных данных или текста, содержащих символы, отличные от ASCII. Тип контента "multipart/form-data" должен использоваться для отправки форм, содержащих файлы, данные, отличные от ASCII, и двоичные данные.

Это означает, что вам нужно подать

файлы, данные, отличные от ASCII, и двоичные данные

вы должны использовать метод POST

+15
источник

Кажется, всегда возникает некоторая путаница в том, когда использовать HTTP POST в сравнении с методом HTTP PUT для служб REST. Большинство разработчиков попытаются связать операции CRUD напрямую с методами HTTP. Я буду утверждать, что это неверно, и нельзя просто связать концепции CRUD с методами HTTP. То есть:

Create => HTTP PUT
Retrieve => HTTP GET
Update => HTTP POST
Delete => HTTP DELETE

Верно, что R (etrieve) и D (elete) операций CRUD могут быть сопоставлены непосредственно HTTP-методам GET и DELETE соответственно. Однако путаница заключается в операциях C (reate) и U (update). В некоторых случаях можно использовать PUT для создания, тогда как в других случаях потребуется POST. Неопределенность заключается в определении метода HTTP PUT и метода HTTP POST.

В соответствии с спецификациями HTTP 1.1 методы GET, HEAD, DELETE и PUT должны быть идемпотентными, а метод POST не является идемпотентным. То есть операция является идемпотентной, если она может выполняться на ресурсе один или несколько раз и всегда возвращает одно и то же состояние этого ресурса. В то время как операция без idempotent может возвращать измененное состояние ресурса от одного запроса другому. Следовательно, в не идемпотентной операции нет гарантии, что вы получите одно и то же состояние ресурса.

Основываясь на приведенном выше определении idempotent, я беру на себя использование метода HTTP PUT или используя метод HTTP POST для служб REST: Используйте метод HTTP PUT, когда:

The client includes all aspect of the resource including the unique identifier to uniquely identify the resource. Example: creating a new employee.
The client provides all the information for a resource to be able to modify that resource.This implies that the server side does not update any aspect of the resource (such as an update date).

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

The server will provide some information concerning the newly created resource. For example, take a logging system. A new entry in the log will most likely have a numbering scheme which is determined on the server side. Upon creating a new log entry, the new sequence number will be determined by the server and not by the client.
On a modification of a resource, the server will provide such information as a resource state or an update date. Again in this case not all information was provided by the client and the resource will be changing from one modification request to the next. Hence a non idempotent operation.

Заключение

Не напрямую связывать и сопоставлять операции CRUD с методами HTTP для служб REST. Использование метода HTTP PUT в сравнении с методом HTTP POST должно основываться на идемпотентном аспекте этой операции. То есть, если операция идемпотентна, используйте метод HTTP PUT. Если операция не является идемпотентной, используйте метод HTTP POST.

+14
источник

Читатели, новые к этой теме, будут поражены бесконечным обсуждением того, что вы должны делать, и относительным отсутствием уроков из опыта. Тот факт, что REST является "предпочтительным" по сравнению с SOAP, я полагаю, высокоуровневое обучение на основе опыта, но доброта, которую мы, должно быть, продвинулись оттуда? Это 2016. Ройская диссертация была в 2000 году. Что мы разработали? Это было весело? Легко ли было интегрироваться? Поддерживать? Будет ли он справляться с ростом смартфонов и взломанными мобильными соединениями?

По мнению ME, реальные сети ненадежны. Требуется тайм-аут. Соединения сбрасываются. Сети работают в течение нескольких часов или дней. Поезда отправляются в туннели с мобильными пользователями на борту. По любому запросу (как это иногда признается во всех этих обсуждениях) запрос может попасть в воду на своем пути, или ответ может упасть в воду на обратном пути. В этих условиях выдача запросов PUT, POST и DELETE непосредственно к основным ресурсам всегда казалась мне немного жестокой и наивной.

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

Или вы можете это сделать: рассмотрите ваши небезопасные запросы как эфемерные однопользовательские ресурсы (позвольте им называть их действия). Клиенты запрашивают новое "действие" на основном ресурсе с пустым POST ресурсом. POST будет использоваться только для этого. После безопасного хранения URI недавно отчеканенного действия клиент выдает небезопасный запрос к URI действия, а не целевой ресурс. Урегулирование действия и обновление "реального" ресурса - это должным образом работа вашего API и здесь отключена от ненадежной сети.

Сервер выполняет бизнес, возвращает ответ и сохраняет его в соответствии с URI согласованного действия. Если что-то пойдет не так, клиент повторяет запрос (естественное поведение!), И если сервер уже видел его, он повторяет сохраненный ответ и ничего не делает.

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

Лучше всего, мы даем возможность отправлять и получать приложения, чтобы связать уникально идентифицированное действие с уникальностью в их соответствующих средах. И мы можем начать требовать и обеспечивать соблюдение !, ответственное поведение клиентов: повторяйте свои запросы так, как вам нравится, но не начинайте генерировать новое действие, пока не получите окончательный результат от существующего.

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

Последовательные запросы на удаление могут видеть и обрабатывать исходное подтверждение без ошибки 404. Если что-то происходит дольше, чем ожидалось, мы можем отреагировать временно, и у нас есть место, где клиент может проверить окончательный результат. Наилучшей частью этого шаблона является его свойство Kung-Fu (Panda). Мы принимаем слабость, склонность клиентов повторять запрос в любое время, когда они не понимают ответ, и превращают его в силу :-)

Прежде чем сказать мне, что это не RESTful, рассмотрите многочисленные способы уважения принципов REST. Клиенты не создают URL-адреса. API остается доступным, хотя и с небольшим изменением в семантике. HTTP-глаголы используются соответствующим образом. Если вы считаете, что это огромное изменение для реализации, я могу сказать вам по опыту, что это не так.

Если вы считаете, что у вас будет огромное количество данных для хранения, позвольте говорить томам: типичное подтверждение обновления составляет часть килобайта. HTTP в настоящее время дает вам минуту или две, чтобы ответить окончательно. Даже если вы только сохраняете действия в течение недели, у клиентов есть достаточный шанс догнать. Если у вас очень большие объемы, вам может потребоваться специализированное хранилище значений ключа, соответствующее кислотам, или решение в памяти.

+14
источник

исходный сервер может создать ресурс с этим URI

Таким образом, вы используете POST и, возможно, но не обязательно PUT для создания ресурса. Вам не нужно поддерживать оба. Для меня POST вполне достаточно. Итак, это дизайнерское решение.

Как упоминалось в вашей цитате, вы используете PUT для создания ресурса, назначенного IRI, и вы все равно хотите создать ресурс. Например, PUT /users/123/password обычно заменяет старый пароль новым, но вы можете использовать его для создания пароля, если он еще не существует (например, только что зарегистрированным пользователям или путем восстановления запрещенных пользователей).

+13
источник

Я собираюсь приземлиться со следующим:

PUT относится к ресурсу, идентифицированному URI. В этом случае вы обновляете его. Это часть трех глаголов, ссылающихся на ресурсы - удаляйте и становитесь двумя другими.

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


Поскольку PUT и GET и DELETE относятся к ресурсу, они также по определению идемпотент.

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

A PUT не нужно создавать; служба может ошибиться, если ресурс еще не создан, но в противном случае его обновит. Или наоборот - он может создать ресурс, но не разрешать обновления. Единственное, что требуется для PUT, это указание на определенный ресурс, а его полезная нагрузка - это представление этого ресурса. Успешный PUT означает (запрет помех), что GET будет извлекать один и тот же ресурс.


Изменить: Еще одна вещь - PUT может создавать, но если это так, то идентификатор должен быть естественным ID - AKA адресом электронной почты. Таким образом, когда вы дважды вставляете, второй ставит обновление первого. Это делает его идемпотентным.

Если идентификатор сгенерирован (например, новый идентификатор сотрудника), то второй PUT с тем же URL-адресом создаст новую запись, которая нарушает правило idempotent. В этом случае глагол будет POST, а сообщение (а не ресурс) будет состоять в создании ресурса с использованием значений, определенных в этом сообщении.

+11
источник

Предполагается, что семантика различна, поскольку "PUT", например "GET", должен быть идемпотентным, то есть вы можете иметь один и тот же точный запрос PUT несколько раз, и результат будет таким, как если бы вы выполнили его только один раз,

Я опишу соглашения, которые, по моему мнению, наиболее широко используются и являются наиболее полезными:

При запуске ресурса по определенному URL-адресу происходит то, что он должен быть сохранен на этом URL-адресе или что-то в этом роде.

Когда вы отправляете POST на ресурс по определенному URL-адресу, вы часто отправляете связанный фрагмент информации на этот URL-адрес. Это означает, что ресурс по URL уже существует.

Например, если вы хотите создать новый поток, вы можете нажать его на некоторый URL. Но когда вы хотите отправить сообщение POST в существующий поток, вы отправляете POST по его URL-адресу.

Что касается модификации свойств потока, вы можете сделать это с помощью PUT или POST. В принципе, используйте только "PUT", когда операция идемпотентна, иначе используйте POST.

Обратите внимание, однако, что не все современные браузеры поддерживают HTTP-глаголы, отличные от GET или POST.

+9
источник

В большинстве случаев вы будете использовать их следующим образом:

  • POST ресурс в коллекцию
  • PUT ресурс, идентифицированный с помощью коллекции /: id

Например:

  • POST/items
  • PUT/items/1234

В обоих случаях тело запроса содержит данные для создаваемого или обновляемого ресурса. Из названий маршрутов должно быть очевидно, что POST не является идемпотентным (если вы вызываете его 3 раза, он будет создавать 3 объекта), но PUT является идемпотентным (если вы его назовете 3 раза, то результат будет таким же). PUT часто используется для операции "upsert" (создание или обновление), но вы всегда можете вернуть ошибку 404, если хотите использовать ее только для изменения.

Обратите внимание, что POST "создает" новый элемент в коллекции, а PUT "заменяет" элемент по заданному URL-адресу, но очень часто используется PUT для частичных модификаций, то есть использовать его только для обновления существующие ресурсы и только модифицировать включенные поля в теле (игнорируя другие поля). Это технически некорректно, если вы хотите быть REST-пуристом, PUT должен заменить весь ресурс, и вы должны использовать PATCH для частичного обновления. Мне лично все равно, насколько поведение ясное и последовательное во всех ваших конечных точках API.

Помните, что REST - это набор конвенций и рекомендаций, которые упрощают ваш API. Если вы закончите сложную работу, чтобы проверить поле "RESTfull", вы побеждаете цель;)

+8
источник

Здесь простое правило:

PUT URL-адрес должен использоваться для обновления или создания ресурса, который может быть расположен по этому URL-адресу.

POST URL-адрес должен использоваться для обновления или создания ресурса, который находится на каком-то другом ( "подчиненном" ) URL-адресе, или не доступен для поиска через HTTP.

+7
источник

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

Позвольте быть предельно ясным и прямым здесь. Если вы являетесь разработчиком .NET, работающим с веб-API, факты (из документации Microsoft API), http://www.asp.net/web-api/overview/creating-web-apis/creating-a-web-api-that-supports-crud-operations:

1. PUT = UPDATE (/api/products/id)
2. MCSD Exams 2014 -  UPDATE = PUT, there are **NO** multiple answers for that question period.

Уверен, что вы "можете" использовать "POST" для обновления, но просто следуйте соглашениям, изложенным для вас с вашей картой. В моем случае это .NET/Web API, поэтому PUT для UPDATE нет дискуссий.

Я надеюсь, что это поможет любым разработчикам Microsoft, которые читают все комментарии с ссылками на Amazon и Sun/Java.

+7
источник

Если вы знакомы с операциями с базой данных, есть

  • Выберите
  • Вставить
  • Update
  • Удалить
  • Объединить (обновить, если он уже существует, иначе вставить)

Я использую PUT для Merge и обновляю подобные операции и использую POST для Insertions.

+6
источник

На практике POST хорошо работает для создания ресурсов. URL-адрес вновь созданного ресурса должен быть возвращен в заголовке ответа местоположения. PUT должен использоваться для полного обновления ресурса. Пожалуйста, поймите, что это лучшие практики при разработке RESTful API. Спецификация HTTP как таковая не ограничивает использование PUT/POST несколькими ограничениями для создания/обновления ресурсов. Взгляните на http://techoctave.com/c7/posts/71-twitter-rest-api-dissected, в котором приведены лучшие примеры.

+5
источник
  • 1
  • 2

Посмотрите другие вопросы по меткам или Задайте вопрос