В чем разница между POST и PUT в HTTP?

Согласно RFC 2616, § 9.5, POST используется для создания < / em> ресурс:

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

Согласно RFC 2616, § 9.6, PUT используется для создания или заменить ресурс:

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

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


person alex    schedule 10.03.2009    source источник
comment
Может быть полезно использовать определения в HTTPbis - Рой приложил немало усилий для их разъяснения. См .: tools.ietf.org/html/   -  person Mark Nottingham    schedule 24.10.2011
comment
Чтобы привести комментарий @MarkNottingham к последней версии, вот POST и PUT, как определено в HTTPbis.   -  person Marius Butuc    schedule 18.11.2012
comment
Мне кажется, что эта дискуссия возникла из-за общей практики чрезмерного упрощения REST путем описания методов HTTP в терминах операций CRUD.   -  person Stuporman    schedule 14.02.2013
comment
К сожалению, первые ответы на POST неверны. Посмотрите мой ответ, чтобы лучше понять различия: stackoverflow.com/a/18243587/2458234   -  person 7hi4g0    schedule 25.11.2013
comment
PUT и POST - небезопасные методы. Однако PUT идемпотентен, а POST - нет. - См. Дополнительную информацию по адресу: restcookbook.com/HTTP%20Methods/ put-vs-post /   -  person Dinesh Saini    schedule 11.01.2014
comment
вы знаете ... Я понимаю, что в спецификации PUT упоминается как «обновление», но я думаю, что всех было бы намного меньше смущать, если бы мы сказали, что он «заменен», это то, что он делает в конце концов.   -  person thecoshman    schedule 16.06.2014
comment
На практике POST хорошо работает для создания ресурсов. URL-адрес вновь созданного ресурса должен быть возвращен в заголовке ответа Location. PUT следует использовать для полного обновления ресурса. Пожалуйста, поймите, что это лучшие практики при разработке RESTful API. Спецификация HTTP как таковая не ограничивает использование PUT / POST с некоторыми ограничениями для создания / обновления ресурсов. Взгляните на techoctave.com/c7/posts/71-twitter- rest-api-exclucted, в котором обобщены лучшие практики.   -  person java_geek    schedule 06.10.2014
comment
idempotency - это ключ. Прочтите PUT или POST: ОТДЫХ по рассказу Джона Калкота. Если ваш метод идемпотентен, используйте PUT. Если нет, используйте POST.   -  person LCJ    schedule 11.08.2016
comment
Я не понимаю преобладающего мнения по этому поводу. Цитата OP для PUT начинается с того, что метод PUT запрашивает, чтобы закрытый объект был сохранен .... Это кричит мне о создании. Когда мы говорим о том, чтобы что-то куда-то положить, мы говорим о месте, где этого раньше не было. Вы ничего не кладете, чтобы это изменить. Когда вы вносите поправки в документ, вы не добавляете новый. Использование HTTP-глагола PUT для обозначения обновления является плохим семантическим соответствием.   -  person Keith Tyler    schedule 28.03.2017
comment
PUT начинался как способ публикации контента непосредственно на сервере в первых инструментах разработки Microsoft HTML. Тот факт, что он также использовался для обновления (оптовой продажи), был связан с отсутствием другого метода обновления. Несмотря на то, что это было массовое обновление, это действительно было творение, только идемпотентное. Обновление подразумевает, что некоторые аспекты предыдущего состояния были сохранены.   -  person Keith Tyler    schedule 28.03.2017
comment
Сценарий реального мира в эластичной документации: elastic.co/guide/en / elasticsearch / reference / current /. Посмотрите на разницу между всеми запросами PUT и последним примером запроса POST.   -  person DevDio    schedule 10.04.2018
comment
JavaBrains объясняет это очень ясно. Взгляните на youtube.com/watch?v=rhTkRK53XdQ   -  person Ram    schedule 17.08.2018
comment
Различия между методами POST и PUT следует описывать в определенном контексте. Например, здесь вопрос касается REST, и на самом деле речь идет о согласованности и единообразном интерфейсе. Пока вы соблюдаете согласованность дизайна API, у вас все хорошо.   -  person lokesh    schedule 17.08.2018
comment
Обратите внимание: если вы хотите, чтобы веб-приложение работало, даже если JavaScript отключен, вам следует использовать POST: stackoverflow.com/questions/630453/put-vs-post-in-rest/   -  person baptx    schedule 26.06.2019
comment
Приложенная цитата OP о POST больше не действительна. Фактическая функция, выполняемая методом POST, определяется сервером и обычно зависит от действующего URI запроса. Действие, выполняемое методом POST, может не привести к ресурсу, который можно идентифицировать с помощью URI. через tools.ietf.org/html /   -  person sindhu_sp    schedule 13.11.2019
comment
Идемпотентность важна. Но чтобы быть идемпотентным, у вас должен быть уникальный ключ (или набор ключей). Если уникальный ключ указан в вызове POST дважды, второй должен сгенерировать ошибку. В вызове PUT он должен создать / обновить / заменить ресурс. Можно выполнить вызов POST без предоставления уникального ключа (он просто каждый раз создает новый ресурс). Однако выполнить вызов PUT без ключа невозможно.   -  person rfportilla    schedule 28.10.2020
comment
Все эти разговоры о том, что PUT является идемпотентным, а POST нет, игнорируют слона в комнате. Браузер повторит попытку любого из них, даже POST, если соединение закрыто сервером, поэтому вам необходимо разработать свой API так, чтобы он был идемпотентным, поэтому, когда это произойдет с вами, вы не сможете жаловаться! :) Выбор метода практически спорный. stackoverflow.com/questions/15155014/ w3.org/Protocols/rfc2616/rfc2616-sec8.html#sec8.2.4   -  person Tony B    schedule 07.11.2020


Ответы (35)


Общий:

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

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

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

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

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

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

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

Пример:

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

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/

Кроме того, немного более кратко, RFC 7231, раздел 4.3.4 PUT состояния (курсив наш),

4.3.4. PUT

Метод PUT запрашивает, чтобы состояние целевого ресурса было created или replaced с состоянием, определенным представлением, заключенным в полезную нагрузку сообщения запроса.

person Brian R. Bondy    schedule 10.03.2009
comment
Я думаю, что нельзя достаточно подчеркнуть тот факт, что PUT является идемпотентным: если сеть испорчена и клиент не уверен, прошел ли его запрос, он может просто отправить его второй (или сотый) раз, и это гарантируется HTTP указывает, что это имеет тот же эффект, что и однократная отправка. - person Jörg W Mittag; 10.03.2009
comment
@ Jörg W Mittag: Не обязательно. Второй раз может вернуть 409 Conflict или что-то еще, если запрос был изменен тем временем (каким-то другим пользователем или самим первым запросом, который прошел). - person Mitar; 28.11.2011
comment
Думаю, разницы в определении нет. 409 Конфликт может быть результатом даже для первого запроса клиента. В любом случае он должен исследовать проблему. - person Mitar; 28.11.2011
comment
Если я не ошибаюсь, мы должны подчеркнуть, что PUT определен как идемпотентный. Вам все равно нужно написать свой сервер таким образом, чтобы PUT вел себя правильно, да? Возможно, лучше сказать, что PUT заставляет транспорт принимать идемпотентность, что может повлиять на поведение транспорта, например кеширование. - person Ian Ni-Lewis; 28.12.2011
comment
На веб-сайте Пола Прескода есть несколько идей о том, как сделать POST более надежным, хотя сайт в целом похоже, не обновляется. - person hotshot309; 04.04.2012
comment
Чтобы прояснить ситуацию, можно добавить, что этот пример должен возвращать ошибку: PUT / questions HTTP / 1.1 Host: wahteverblahblah.com - person Martin Brown; 04.10.2013
comment
Я поддерживаю это, @MartinBrown ... на самом деле, ваша точка зрения меня очень многое проясняет. Ответ в его нынешнем виде уже фантастичен, не поймите меня неправильно! - person Eric Fuller; 23.10.2013
comment
@ JörgWMittag Ключевая фраза идемпотентности? Как насчет Отправить, отправить и отправить моего друга, в конце концов, это не имеет значения. - person James Beninger; 03.03.2014
comment
PUT следует использовать для создания ресурса только в том случае, если клиент заботится об имени ресурса. Клиент, заботящийся о названии ресурса, указывает на связь. Сцепление - результат плохой практики. Поэтому используйте POST. Если есть опасения по поводу того, что ресурс создается дважды с помощью POST (поскольку он не идемпотент), прочтите этот ответ. - person Joshcodes; 17.03.2014
comment
@ JörgWMittag Если PUT является идемпотентным, что произойдет, если PUT создает новый ресурс, а сервер генерирует идентификатор объекта? Это означало бы, что каждый вызов PUT будет создавать другой идентификатор объекта. Означает ли это, что в этом случае нельзя / нельзя использовать PUT, а вместо этого требуется POST? - person Eric B.; 09.07.2014
comment
@EricB. Идентификатор объекта - это то, что он называет именем. Таким образом, он должен быть предоставлен как часть URL-адреса при использовании POST, а не генерироваться сервером. - person Legogris; 22.09.2014
comment
На практике POST хорошо работает для создания ресурсов. URL-адрес вновь созданного ресурса должен быть возвращен в заголовке ответа Location. PUT следует использовать для полного обновления ресурса. Пожалуйста, поймите, что это лучшие практики при разработке RESTful API. Спецификация HTTP как таковая не ограничивает использование PUT / POST с некоторыми ограничениями для создания / обновления ресурсов. - person java_geek; 06.10.2014
comment
Одно примечание об использовании POST для обновлений стиля CRUD: я знаю, что Рой Филдинг указал, что для RESTful-дизайна должно быть более важным использовать гипермедиа и обнаруживаемые самообъясняемые API, чем (например) запрещать запросы POST для выполнения обновлений элементов. Но процитированная спецификация http дает практическое правило: в целом вполне интуитивно понятно и последовательно разрешить POST только для создания новых подчиненных для данного ресурса. Для замены или обновления существующих ресурсов я всегда предпочитаю PUT или PATCH. - person matthias; 12.03.2015
comment
Каким бы ни было семантическое значение POST vs PUT: если вам нужно поддерживать IE9 и IE8, имейте в виду, что запросы CORS в этих версиях не поддерживают PUT - только GET / POST. См. blogs.msdn .com / b / ieinternals / archive / 2010/05/13 / - person flexponsive; 10.04.2015
comment
Может кто-нибудь уточнить это предложение. С помощью POST вы можете иметь 2 запроса, которые одновременно вносят изменения в URL-адрес, и они могут обновлять разные части объекта. Пожалуйста, объясните, почему это относится к POST, а не к PUT? - person Kevin Wheeler; 09.09.2015
comment
@KevinWheeler: У Билла де Хора есть хорошая запись в блоге об использовании POST для обновления только некоторых полей ресурса, тогда как PUT должен предоставлять все поля (будь то создание или обновление): dehora.net/journal/2009/02/03/just-use-post Он подчеркивает, что PUT может быть очень тяжелым, если вам нужно отправить через все поля, когда вы хотите обновить только одно. Итак, следуя его схеме, вы могли бы отправить POST-запрос через обновление пары полей и еще один запрос POST, обновив еще пару полей в том же ресурсе. Не уверен, но я думаю, что теперь PATCH делает то же самое. - person Simon Tewsi; 14.01.2016
comment
Считает их: PUT = вставить или обновить; POST = вставить. Итак, когда вы делаете два PUT - вы получаете одну новую запись, когда вы выполняете два POST - вы получаете две новые записи. - person Eugen Konkov; 22.08.2016
comment
С помощью POST вы можете получать 2 запроса, которые одновременно вносят изменения в URL-адрес, и они могут обновлять разные части объекта. .......... ты имеешь ввиду POST может обновлять? - person Raúl; 11.11.2016
comment
Используется для изменения и обновления ресурса ....... вы должны иметь в виду «или» - верно? - person Raúl; 11.11.2016
comment
@ Ученик, я разделяю ваше мнение. Этот ответ и примеры сбивают с толку. Слова используются непоследовательно. - person lucid_dreamer; 18.06.2017
comment
Думайте как сервер: ожидайте, что элемент будет однозначно идентифицируемым. Если я получу PUT без идентификатора, я отклоню его, потому что он не сообщает мне, что обновлять. Если я получу POST с идентификатором, я отклоню его, потому что я не могу создать то, что уже существует. - person Brian Lowe; 20.07.2017
comment
Предполагая, что у меня есть следующий URL-адрес: test.awesome.com/questions, означает ли вышесказанное, что я должен ПОЛУЧИТЬ на этот URL-адрес, чтобы создать новый ресурс? Я думал, что это POST для коллекции и PUT для URL-адреса с указанным идентификатором. Разве это не ПОСТАВЛЯЕТСЯ здесь: test.awesome.com/questions/1 и РАЗМЕЩАЕТСЯ здесь: test.awesome.com/questions? Или он говорит, что если test.awesome.com/questions/1 не существует, PUT создаст его или заменит, если он уже существует на сервере? - person cr1pto; 22.09.2017
comment
Означает ли идемпотентность PUT, что у нас не может быть одного и того же имени ресурса или что объекты с одинаковыми хэшами не могут существовать одновременно? - person monolith; 21.11.2017
comment
@wedran idempotency означает, что если кто-то вызовет PUT один или несколько раз, результат останется прежним. Таким образом, операция, в которой каждый вызов вызывает изменение (например, увеличивается счетчик), не будет идемпотентной (restapitutorial.com/lessons/idempotency.html). Я бы рекомендовал прочитать здесь все ответы, чтобы лучше понять. Это не имеет ничего общего с именем ресурса или хешем. - person skofgar; 22.11.2017
comment
Я ошибаюсь, или этот ответ противоречит информации в вопросе? Там написано Post = Create. Поставьте = Обновить, если возможно. Если нет, создайте. Однако здесь написано «Post = Update». Я запутался. - person Mark A. Donohoe; 16.12.2017
comment
Вы действительно должны использовать PATCH для обновления объекта, PUT для вставки объекта, DELETE для удаления / удаления объекта и POST для выполнения других действий, таких как отправка запросов типа данных формы. - person SynackSA; 19.01.2018
comment
Было бы неплохо, если бы мы могли добавить разницу с помощью PATCH. Прямо сейчас я нахожусь в ситуации, когда я заранее определяю идентификатор ресурса (а не сервер), поэтому я использую PUT для его создания, а затем POST для его обновления, но я также мог бы использовать PATCH вместо POST, и это бы имеют больше смысла, семантически говоря. - person Vadorequest; 20.02.2018
comment
@ BrianR.Bondy Вы написали: POST: используется для изменения и обновления ресурса POST / questions / ‹existing_question› HTTP / 1.1. Но в этом случае вы делаете метод POST идемпотентным. Это контрастирует со спецификацией HTTP! RFC 7231 - person Glauco Cucchiar; 02.03.2018
comment
@ BrianR.Bondy в определениях ссылок ниже противоречат restfulapi.net/rest-put-vs- сообщение - person ; 10.04.2018
comment
@Sirius - я думал то же самое, но технически POST можно использовать для добавления к существующему ресурсу, как указано в Раздел 4.3.3 RFC 7231 - 4-й маркер. Я бы рассмотрел возможность добавления как обновления, но это можно интерпретировать по-другому. - person commandt; 03.05.2018
comment
Вам не нужно поддерживать как PUT, так и POST, за следует, Если URL-адрес еще не создан, вы не должны использовать POST для его создания при указании имени ... Вы должен сначала ПОСТАВИТЬ ресурс ‹new_question› на сервере. Возможно, Вам не нужно поддерживать POST, если вы поддерживаете PUT? Или @SynackSA что-то интересует? - person ruffin; 30.08.2018
comment
Означает ли идемпотент, что если ресурс уже существует и похож, метод PUT сохраняет некоторый ресурс, преодолевая точку и переходя непосредственно к следующей точке? Другими словами, своего рода оптимизация сохранения - person Webwoman; 03.09.2018
comment
Разве утверждение автора о том, что POST можно использовать для изменения / обновления, неверно? Например, он использует POST /questions/<existing_question> , что означает, что запрос POST знает о местонахождении ресурса, который равен <existing_question>, но это означает, что POST показывает idempotent behavior причину, независимо от того, сколько раз мы делаем этот запрос, к тому же ресурсу (<existing_question>) будет осуществлен доступ в сервер, который не является правильным, поскольку POST должен быть non-idempotent, что означает, что каждый раз, когда мы вызываем его, он должен изменять состояние сервера. - person Yug Singh; 30.09.2018
comment
put СЛЕДУЕТ рассматривать как модифицированную версию - допустимо, чтобы PUT для существующего объекта не выполнял обновление. но рекомендуется, чтобы это было - person Jasen; 18.01.2019
comment
для PUT вместо создания я предпочитаю говорить «связать или изменить существующее», это намного точнее - person user1438644; 18.04.2019
comment
Я думаю, что ответ по поводу POST неправильный. POST / questions / ‹existing_question› не следует использовать. Используйте POST / questions для создания нового вопроса без знания идентификатора вопроса. Используйте PUT / questions / ‹questionId›, чтобы создать (в случае, если клиент управляет идентификаторами вопросов, иначе используйте POST) или замените (полностью) вопрос, зная идентификатор вопроса. Используйте PATCH для частичного изменения. - person Guillaume Vauvert; 17.07.2019
comment
Просто чтобы взглянуть на вещи в перспективе большого слова идемпотент. Это просто означает, что POST похож на myWallet.AddMoney (999), а PUT - это myWallet.SetMoney (999). - person BoBoDev; 06.08.2020
comment
@EugenKonkov - Итак, что происходит, когда я использую сообщение для обновления существующего ресурса, как указано в ответе? Возвращаем ли мы новый ресурс или обновления применяются к существующему ресурсу? - person MasterJoe; 10.09.2020
comment
@ JörgWMittag - См. Комментарий Евгения Конькова. Это звучит правильно? Вот комментарий - думает о них как о: PUT = вставить или обновить; POST = вставить. Итак, когда вы делаете два PUT - вы получаете одну новую запись, когда вы выполняете два POST - вы получаете две новые записи. - person MasterJoe; 10.09.2020
comment
@MasterJoe: indepondent означает, что, несмотря на все ваши запросы, вы получите тот же результат. Для НАШЕЙ ПУТ. Когда вы сделали один запрос - вы получите одну запись в базе с вашим dara. Когда вы сделали два запроса - вы получите одну запись в базе данных с вашими данными. Когда вы выполнили N запросов , вы получите одну запись в базе данных с вашими данными. Когда вы выполняете запрос POST - после каждого запроса вы будете получать новую дополнительную запись в базе данных с вашими (отправленными) данными. - person Eugen Konkov; 11.09.2020
comment
@MasterJoe: Никакой орган не запрещает вам делать POST-запросы к вашему сайту независимо. Это зависит от API вашего сайта. Вероятно, это будет просто сюрпризом для ваших пользователей, которые не читают документацию по вашему API. - person Eugen Konkov; 11.09.2020
comment
Мы отправляем данные через оба. И делаем все, что хотим, с обоими - person Ali.Rashidi; 24.06.2021

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

Ни то, ни другое не совсем верно.


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

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

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


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

so:

POST /expense-report

or:

PUT  /expense-report/10929
person Cheeso    schedule 22.04.2010
comment
Я согласен, что когда речь идет об идемпотентности, она должна преобладать над любыми другими проблемами, поскольку ошибка может вызвать множество неожиданных ошибок. - person Josh; 26.10.2010
comment
да. Фактически, протокол AtomPub бросает вызов этому (или, точнее, ограничивает его семантическое значение PUT): PUT используется для редактирования известного ресурса. Он не используется для создания Ресурса. Тот факт, что протокол AtomPub говорит об этом (что, кстати, действительно), не означает, что все протоколы RESTful должны следовать ему. (потому что REST является общим) - person Hendy Irawan; 14.04.2011
comment
Если POST может обновить ресурс, как это не идемпотентный? Если я изменю возраст учащихся с помощью PUT и сделаю это в 10 раз, возраст учащихся будет таким же, как если бы я сделал это один раз. - person Jack Ukleja; 06.05.2011
comment
@Schneider, в этом случае ваш сервер прилагает дополнительные усилия, чтобы гарантировать идемпотентность, но не рекламирует это. Браузеры по-прежнему будут предупреждать пользователя, если они попытаются перезагрузить такой запрос POST. - person Tobu; 06.01.2012
comment
@Schneider POST может создать дополнительный ресурс; следовательно, вы можете POST для сбора, например POST / отчет о расходах, и он создаст на вашем сервере столько сущностей (отчетов о расходах), сколько количество отправленных вами запросов, даже если они полностью похожи . Подумайте об этом как о вставке той же строки в таблицу БД (/ отчет о расходах) с автоматически увеличивающимся первичным ключом. Данные остаются прежними, ключ (в данном случае URI) генерируется сервером и отличается для каждой другой вставки (запроса). Таким образом, эффект POST может быть идемпотентным, но также может нет. Следовательно, POST не идемпотентен. - person Snifff; 26.01.2012
comment
Это мертво, и принятые ответы надеются, что я (@brian) пропущу эту важную тонкость. - person Andrew Roberts; 21.03.2012
comment
Допустим, у нас есть объекты, которые могут иметь два свойства - name и date. Если у нас есть сущность с существующими name и date, но затем мы делаем запросы к ней с указанием только name, правильным поведением PUT будет уничтожение date сущности, тогда как POST может обновлять только указанные свойства, оставляя неуказанные свойства такими, какими они были до отправки запроса. Звучит ли это правильно / разумно, или это неправильное использование PUT (я видел ссылки на PATCH, которые кажутся более подходящими, но пока не существуют )? - person Jon z; 08.05.2013
comment
Это совершенно неправильно. Идемпотентность не должна определять, используется ли PUT или POST. Кто несет ответственность за структуру URL, решает, используется ли PUT или POST. Чтобы понять, как обрабатывать повторяющиеся запросы POST, см. этот ответ. - person Joshcodes; 24.04.2014
comment
Интересно, имеет ли он в виду под POST возможность обновления ресурса то, что, отправляя POST в коллекцию, вы добавляете к ней элемент и, следовательно, обновляете коллекцию. Это различие кажется немного вводящим в заблуждение. Хотя мне нравится ответ. - person Thomas; 28.05.2015
comment
Спасибо, это очень помогло. Чтобы продолжить вашу аналогию, POST может использоваться для назначения (в отличие от x++), но это больше похоже на obj.setX(5) - метод setX должен привести к тому, что x будет равно 5, но может иметь побочные эффекты. - person Nicole; 02.10.2015
comment
Если вы используете POST для частичного обновления существующего ресурса, например, для обновления только пары полей, можете ли вы указать имя ресурса? Причина, по которой я спрашиваю, заключается в том, что многие люди говорят, что POST нельзя использовать с отдельным ресурсом, только с его родительской коллекцией. например, POST применяется к отчетам о расходах. Можно ли обновить, скажем, одно поле отчета о расходах 10929, используя POST /expense-report/10929? - person Simon Tewsi; 14.01.2016
comment
Я согласен с этим ответом. Ключевое отличие - идемпотентность PUT. Я нашел очень хорошее объяснение идемпотентности на stormpath.com/blog/put-or-post - person Naymesh Mistry; 05.09.2016
comment
Сравнение PUT и POST с mysql: POST похоже на INSERT INTO без указания идентификатора столбца с автоинкрементом, если вы делаете это несколько раз , вы создадите несколько строк. PUT похож на UPDATE, использующий первичный ключ в операторе WHERE, если вы сделаете это несколько раз, строка должна быть одинаковой после каждого из них. Некоторые поставщики также могут разрешить вам PUT для создания, что будет похоже на INSERT INTO, предоставляющее значение для столбца автоинкремента. - person Jo.; 16.03.2017
comment
Нет ничего, что говорило бы, что вы не можете реализовать POST как идемпотентный, все, что говорит стандарт, это то, что он рассматривается как небезопасный. Реализация идемпотентного сообщения для создания ресурса, где клиент может сгенерировать идентификатор и передать токен запроса для определения повторных попыток, работает хорошо .. например, / api / foobars / {GUID}? Request = {AnotherGUID} - person nrjohnstone; 20.08.2017
comment
Полезная мнемоника: То же PUT ent - person Mercury; 04.09.2019

  • POST к URL-адресу создает дочерний ресурс по определенному сервером URL.
  • PUT в URL создает / заменяет ресурс целиком по определенному клиентом URL.
  • ПАТЧ к URL-адресу обновляет часть ресурса по указанному клиентом URL-адресу.

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

POST создает дочерний ресурс, поэтому POST to /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»

Идея техники «REST без PUT» состоит в том, что потребители вынуждены публиковать новые «именные» ресурсы запроса. Как обсуждалось ранее, изменение почтового адреса клиента - это POST для нового ресурса ChangeOfAddress, а не PUT ресурса «Клиент» с другим значением поля почтового адреса.

взято из REST API Design - Resource Modeling, автор Prakash Subramaniam из Thoughtworks

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

person Nigel Thorne    schedule 07.04.2010
comment
Или с другой стороны забора: PUT, если клиент определяет адрес полученного ресурса, POST, если это делает сервер. - person DanMan; 28.11.2012
comment
Я думаю, что этот ответ следует отредактировать, чтобы прояснить, на что указал @DanMan, очень простым способом. Что я считаю наиболее ценным, так это примечание в конце, в котором говорится, что PUT следует использовать только для замены всего ресурса. - person Hermes; 27.11.2013
comment
PATCH - нереальный вариант по крайней мере несколько лет, но я согласен с идеологией. - person crush; 03.10.2014
comment
Я пытаюсь понять, но использование PUT для создания чего-либо имеет смысл только в том случае, если клиент точно знает, что ресурс еще не существует, верно? Следуя примеру блога, предположим, что вы создали сотни сообщений в блоге за пару лет, а затем случайно выбрали тот же заголовок, что и для сообщения два года назад. Теперь вы заменили этот пост, который не был предназначен. Таким образом, использование PUT для создания потребует от клиента отслеживания того, что принимается, а что нет, и может привести к несчастным случаям и непреднамеренным побочным эффектам, а также иметь маршруты, которые делают две совершенно разные вещи? - person galaxyAbstractor; 30.01.2015
comment
Ты прав. Размещение сообщения в блоге по тому же URL-адресу, что и существующее, приведет к обновлению этого существующего сообщения (хотя вы, очевидно, можете сначала проверить с помощью GET). Это указывает на то, почему было бы плохой идеей использовать только заголовок в качестве URL-адреса. Однако это сработает везде, где есть естественный ключ в данных ... что, по моему опыту, редко. Или если вы использовали GUID - person Nigel Thorne; 03.02.2015
comment
@crush: Почему PATCH не является реалистичным вариантом по крайней мере несколько лет? - person arthropod; 21.06.2016
comment
@NigelThorne Единственный ответ, в котором говорится о URL-адресах, определенных сервером и клиентом. Кто выполняет проверку URL-адресов, определенных клиентом? - person realPK; 27.07.2016
comment
@PK_ сервер проверяет URL. Клиент должен придерживаться схемы URL-адресов, поддерживаемой сервером. Недействительные URL-адреса будут отклонены сервером. - person Nigel Thorne; 30.08.2016
comment
Я работаю над проектом, идентификаторы которого известны клиенту. Поэтому я хотел бы использовать PUT для создания. Однако коллега не согласен с аргументом о том, что было бы запутанно, если бы ресурс был удален, в то время как кто-то другой выполняет PUT (для обновления в целом), теперь ресурс будет воссоздан, даже если он был удален. Он считает, что в сценариях POST, PUT, DELETE PUT должен возвращать 404, если кто-то хочет обновить ресурс, а он не существует. Есть мысли, которые могут помочь? - person skofgar; 22.11.2017
comment
HTTP говорит ... когда клиент "помещает" URL-адрес, он запрашивает этот URL-адрес для хранения этих данных. Сервер должен решить, согласен ли он это сделать. Если вы хотите, чтобы «УДАЛИТЬ» остановили работу ПОМЕЩЕНИЙ ... тогда это нормально, но сможете ли вы когда-нибудь снова иметь что-нибудь по этому URL-адресу? Если это так, то вам, вероятно, следует пропустить последующий PUT ... в конце концов, один из ваших пользователей пытается разместить контент в этом месте по какой-то причине. Кто скажет, кто был правее? :) ответ ... ваш домен. Делайте то, что моделирует ваш домен. но PUT означает, что я пытаюсь сохранить это здесь. - person Nigel Thorne; 22.11.2017
comment
@skofgar PUT должен быть идемпотентным (несколько идентичных запросов дают один и тот же результат). Это мощная концепция, которая бесконечно упрощает жизнь разработчиков, поскольку это надежная операция. Я согласен с путаницей пользователя в этом сценарии, но я думаю, что вы хотите как можно больше решить эту проблему во внешнем интерфейсе. Это также не редкость и иногда очень полезно (например, если вы редактируете на одной вкладке браузера, а вы по ошибке удаляете ее на другой, то при сохранении ресурс полностью восстанавливается) - person John Neuhaus; 14.05.2018
comment
@skofgar В вашем сценарии (клиенты знают идентификаторы и управляют созданием). А как насчет PUT для создания и PATCH для частичного обновления? Вы сохраняете некоторую пропускную способность, и PATCH может выйти из строя, если ресурс будет удален. - person Marcel Toth; 06.02.2020
comment
Хорошая идея, я не видел, чтобы PATCH использовался очень широко, более того, я хочу, чтобы API был как можно более простым. Но я думаю, что в этом случае было бы разумно использовать PATCH. - person skofgar; 08.02.2020
comment
Я собирался использовать PUT для редактирования профиля, но после прочтения статьи и разговора с клиентом он сказал, что хочет, чтобы пользователи редактировали только определенные части профиля, и я считаю, что это идеальное приложение для / changeAddress чего-то, как указано в сообщение в блоге, поскольку оно возвращает управление сервером. И снимает состояние с клиента. Не говоря уже о том, что теперь я могу записывать такие вещи, как, например, как часто пользователи редактируют свой профиль и что они меняют. - person Hemil; 24.07.2020
comment
Я думаю, это должен быть ответ, потому что он наиболее понятен для меня. - person Huan; 13.02.2021

Резюме:

Создавать:

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

ПОЛОЖИЛ

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

PUT /resources/<newResourceId> HTTP/1.1 

ПОЧТА

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

POST /resources HTTP/1.1

Обновлять:

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

ПОЛОЖИЛ

Обновляет ресурс, используя existingResourceId в качестве идентификатора, в URI / resources или коллекцию.

PUT /resources/<existingResourceId> HTTP/1.1

Объяснение:

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

Примеры:

‹- общий - конкретный ->

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

вы публикуете нового пользователя в коллекцию users .

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

POST /users/john HTTP/1.1

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

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

PUT /users/john HTTP/1.1

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

Спецификация:

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

ПОЧТА

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

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

ПОЛОЖИЛ

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

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

Ссылка:

person 7hi4g0    schedule 14.08.2013
comment
Этот пост помог мне понять, что POST добавляет что-то в качестве дочернего элемента в данную коллекцию (URI), тогда как PUT явно определяет что-то в данном месте URI. - person kwah; 23.11.2013
comment
Это очень разумный способ реализовать CRUD API, совместимый с REST / http. Хорошее чтение: RFC о HTTP, и в частности о том, что является идемпотентным и ожидаемым поведением веб-кеша. Использование POST / PUT ограничено ожидаемым поведением кеша (веб или пользовательский агент) - person mcoolive; 21.10.2014
comment
Я думаю, это лучший ответ: ни один из этих POST не может обновить ерунду о ресурсах. Мне нравится ваше утверждение, обновление можно выполнить только с помощью PUT. - person Thomas; 28.05.2015
comment
Нет, PUT не предназначен для обновления или создания. Это для замены. Обратите внимание, что вы не можете ничем заменить что-либо для создания эффекта созидания. - person thecoshman; 08.06.2015
comment
@thecoshman Я опубликовал в своем ответе соответствующие части спецификации HTTP / 1.1. Прочтите последнюю часть моего ответа под названием Spec. В спецификации четко указано, что PUT используется для создания или обновления объекта. - person 7hi4g0; 08.06.2015
comment
@ 7hi4g0 PUT предназначен для обновления с полной заменой, другими словами, заменяет. Вы ничего не заменяете чем-то или что-то совершенно новым. PUT не предназначен для внесения незначительных изменений (если только вы не попросите клиента внести это незначительное изменение и предоставить всю новую версию, даже то, что осталось прежним). Для частичной модификации предпочтительным методом является PATCH. - person thecoshman; 08.06.2015
comment
@thecoshman Я никогда не говорил, что PUT следует использовать для частичной модификации. Если вам не нравится терминология, могу повторить. В спецификации четко указано, что PUT используется для создания или изменения объекта. - person 7hi4g0; 08.06.2015
comment
@thecoshman Я думаю, вы можете сказать, create или replace, но это два разных действия в соответствии со спецификацией. В любом случае, обновить, изменить, заменить - это только условия. - person 7hi4g0; 08.06.2015
comment
@ 7hi4g0 Я хочу сказать, что если вы прочитаете оставшуюся часть этого предложения из спецификации, вы обновите этот URI, чтобы в этом месте появился совершенно новый ресурс. Таким образом, он заменяет 100% данными, включенными в этот PUT запрос. Точно так же я бы сказал, что create - это просто замена «ничего чем-то». Итак, вы можете сделать это просто глупо, просто сказав PUT для замены. - person thecoshman; 09.06.2015
comment
@thecoshman Вы могли бы, но было бы не слишком ясно, что там тоже описано create. В этом случае лучше быть явным. - person 7hi4g0; 09.06.2015
comment
@ 7hi4g0 Я бы сказал, что POST (обычно) более подходит для создания, но все же. Я думаю, мы можем оставить все как есть, мы, по крайней мере, дали людям разумное обсуждение, чтобы подумать, какая IMO является самой важной вещью, когда у вас есть пушистое «руководство»: P - person thecoshman; 10.06.2015
comment
PUT может использоваться для создания ресурса и подходит для создания ресурсов если клиент отвечает за предоставление Структура URL. Однако маловероятно, что в вашем решении уместно, чтобы клиент предоставил структуру URL-адреса. - person Joshcodes; 11.09.2015
comment
Это был самый полезный ресурс, показывающий разницу между PUT / users / John и POST / users / John. Спасибо. - person PRMan; 30.06.2018
comment
Конечно, вы можете ОТПРАВИТЬ «обновление». Если вы храните предыдущие версии (а есть много причин, по которым вы можете захотеть это сделать), то ваше обновление не идемпотентно и не может быть выражено с помощью PUT. (Или, другими словами, все превращается в коллекцию, когда вы достаточно пристально смотрите на нее) - person CurtainDog; 05.09.2018
comment
проголосовали! любопытный вопрос, когда вы вставляете конфликт, ничего не делайте, я предполагаю, что post - это то, что следует использовать, поскольку put фактически заменит его - person PirateApp; 04.02.2020

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

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

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

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

Публикация дважды с одними и теми же данными означает создание двух одинаковых пользователей с разными идентификаторами. Если дважды вставить одни и те же данные, пользователь будет первым, а второй раз обновит его до того же состояния (без изменений). Поскольку вы в конечном итоге получаете одно и то же состояние после PUT, независимо от того, сколько раз вы его выполняете, он каждый раз считается «одинаково мощным» - идемпотентным. Это полезно для автоматического повторения запросов. Больше никаких «вы уверены, что хотите отправить повторно?», Когда вы нажимаете кнопку «Назад» в браузере.

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

person Alexander Torstling    schedule 23.10.2011
comment
Небрежность может быть причиной того, что его обычно учат, что вам нужны только два глагола: GET и POST. GET для получения, POST для изменения. Даже PUT и DELETE выполнялись с помощью POST. Вопрос о том, что на самом деле означает PUT 25 лет спустя, может быть признаком того, что мы сначала поняли это неправильно. Популярность REST вернула людей к истокам, и теперь мы должны забыть о прошлых плохих ошибках. POST злоупотребляли, и теперь его часто обучают неправильно. Лучшая часть: двойная POST-публикация с одними и теми же данными означает создание двух идентичных [ресурсов]. Отличный момент! - person maxpolk; 01.09.2014
comment
Как вы можете использовать PUT для создания записи по идентификатору, как в вашем примере user 5, если она еще не существует? Вы не имеете в виду update, replace if already exists? или что-то - person Luke; 28.11.2014
comment
@ Коултон: Я имел в виду то, что написал. Вы вставляете пользователя 5, если вы помещаете в / users / 5, а # 5 еще не существует. - person Alexander Torstling; 28.11.2014
comment
@Coulton: И PUT также можно использовать для замены значения существующего ресурса целиком. - person DavidRR; 16.12.2014
comment
Предпочитайте PUT вместо POST ... хотите это оправдать? - person thecoshman; 08.06.2015
comment
@thecoshman: Конечно. Я написал это как общий совет. Я считаю, что PUT идемпотентен, следовательно, лучше с точки зрения сети. POST также является более общим, поэтому, рекомендуя PUT, вы избегаете использования POST в ситуациях, когда PUT было бы достаточно. POST также широко используется из-за ограничений браузера, поэтому его рекомендация положительно повлияет на концепцию REST. Есть также некоторые положительные эффекты в схеме URL-адресов, когда клиенты контролируют построение URL-адреса IMO, но я не могу вписать это в комментарий здесь. - person Alexander Torstling; 08.06.2015
comment
@AlexanderTorstling извините, пока я пытаюсь высвободить веские доводы, которые могут пригодиться другим. Как лучше с точки зрения сети? Конечно, если ваша сеть выходит из строя и вам не удалось получить подтверждение, вы можете просто воссоздать заново, но что, если это сработало, а затем кто-то другой изменил? Ваш re-PUT перезапишет то, что они сделали. Вы говорите так, будто POST имеет дополнительные накладные расходы по сравнению с PUT (где PUT было бы достаточно). Я думаю, что факт чрезмерного использования POST не должен означать, что мы не советуем использовать его, когда это правильный выбор, просто научитесь советовать правильный выбор. Последний пункт довольно субъективен. - person thecoshman; 08.06.2015
comment
@thecoshman: Да, я думал о повторных попытках. Параллелизмом PUT можно управлять с помощью условных заголовков, таких как If-Modified et al. То же самое для POST приведет к более грубой блокировке. Вы имеете право защищать правильный выбор, однако я не собирался запрещать POST. Возможно, лучше было бы использовать PUT, когда это возможно? - person Alexander Torstling; 08.06.2015
comment
@AlexanderTorstling Ну, моя главная мысль заключалась в том, что в вашем ответе говорится, что у вас должно быть предпочтение, без каких-либо оснований для этого. Однако ваши ответы здесь кажутся вполне оправданными. Тем не менее, я не думаю, что это правильное объяснение для использования PUT vs POST. - person thecoshman; 09.06.2015
comment
Вот одно из преимуществ использования POST для создания ресурса по сравнению с PUT. В этом случае, если вы попытаетесь изменить ресурс, который еще не существует (с помощью PUT), вы получите сообщение об ошибке. Чтобы обобщить этот совет за пределами PUT vs POST, постарайтесь не использовать интерфейс, в котором результат / действие зависит от текущего состояния, потому что у пользователя может быть неправильное предположение о текущем состоянии (в приведенном примере он думает, что ресурс уже существует). Используйте два отдельных интерфейса и выдайте ошибку, если текущее состояние не соответствует предварительным условиям. - person Kevin Wheeler; 09.09.2015
comment
PS Я до сих пор не понимаю, что означает «Лучше» с точки зрения сети. Однако я могу придумать, по крайней мере, одну причину, почему PUT был бы лучше с точки зрения сети: результаты можно кэшировать (возможно, с помощью прокси-кеш-сервера). - person Kevin Wheeler; 09.09.2015
comment
Я бы сказал, что дважды POSTing с одними и теми же данными МОЖЕТ привести к появлению двух идентичных пользователей. Если бы я создавал свой API, если кто-то пытался отправить нового пользователя с тем же адресом электронной почты, но с разными данными, я мог бы выдать 409. Если кто-то попытался отправить нового пользователя с идентичными данными, я мог бы выдать 303. Я, вероятно, не хотел бы, чтобы в моей системе было два одинаковых пользователя. - person Dan Jones; 27.12.2015
comment
Я не думаю, что это верно по крайней мере для приложения с базой данных ... поэтому, если у меня есть POST * / createUser / diego и PUT * / createUser / jose, и я дважды щелкнул, и оба с методом persisted (), он вставит 4 записи. - person diego matos - keke; 17.03.2016
comment
@ diegomatos-keke: вы не должны PUT или POST для URI глагола, такого как createUser. Вы должны отправить POST в '* / users', чтобы создать Diego, и PUT в '* / users / diego', чтобы обновить Diego. Если вы дважды щелкните для POST, вы создадите 2 Diegos. Но если вы дважды щелкните для PUT, вы дважды обновите Diego, но не создадите 2 Diegos. - person Alexander Torstling; 17.03.2016
comment
@AlexanderTorstling комментирует, чтобы обратить ваше внимание на stackoverflow.com/questions/39057416/. может ты сможешь помочь. - person Roam; 20.08.2016
comment
это нормально согласно RFC tools.ietf.org/html/rfc2616#page-54 < / а> - person F.Tamy; 07.09.2020

Хочу добавить свой «прагматический» совет. Используйте 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
person ThaDon    schedule 15.01.2011
comment
Собственно, это должно быть POST /users. (Обратите внимание, что /users во множественном числе.) Это влияет на создание нового пользователя и превращение его в дочерний ресурс коллекции /users. - person DavidRR; 16.12.2014
comment
@DavidRR, честно говоря, как обращаться с группами - это еще одна дискуссия. GET /users имеет смысл, он читается так, как вы хотите, но я был бы в порядке с GET /user/<id> или POST /user (с полезной нагрузкой для указанного нового пользователя), потому что он правильно читается, «покажите мне пользователей 5» - это странно, но «получите мне пользователя 5» больше естественный. Хотя, наверное, я бы все же стал сторонником плюрализации :) - person thecoshman; 08.06.2015
comment
@thecoshman Вы можете прочитать это как «от пользователей получите мне идентификатор 5»;) - person xuiqzy; 08.11.2020
comment
@xuiqzy хм, мне очень нравится такой образ мышления, и он прекрасно расширяется GET /users/5/documents/4/title это было бы как 'получить пользователей, оттуда получить меня пользователя 5, оттуда получить мне документы, оттуда получить мне документ 4, оттуда достань мне титул ' - person thecoshman; 18.11.2020

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

PUT POST
Replacing existing resource or creating if resource is not exist. www.example.com/com/customer/{customerId} www.example.com/com/customer/123/order/{orderId} Identifier is chosen by the client. Creating new resources and subordinate resources, e.g. a file is subordinate to a directory containing it or a row is subordinate to a database table. www.example.com/com/customer/ www.example.com/com/customer/123/order/ identifier is returned by server
Idempotent i.e. if you PUT a resource twice, it has no effect. Example: Do it as many times as you want, the result will be same. x=1; POST is neither safe nor idempotent. Example: x++;
Works as specific Works as abstractive
If you create or update a resource using PUT and then make that same call again, the resource is still there and still has the same state as it did with the first call. Making two identical POST requests will most likely result in two resources containing the same information.

Аналогия:

  • PUT, т.е. взять и положить на место.
  • ОТПРАВИТЬ как отправить письмо в почтовое отделение.

введите описание изображения здесь

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

  • Публикация в социальных сетях: когда мы публикуем сообщение, создается новое сообщение.
  • Поместите (т. е. отредактируйте) для уже отправленного сообщения.
person Premraj    schedule 11.09.2015
comment
@MobileMon Нет, методы REST не являются CRUD. - person jlr; 08.01.2016
comment
Я бы сказал PUT для UPSERTS - person Hola Soy Edu Feliz Navidad; 26.11.2018
comment
@MobileMon no: POST, когда вы создаете новый ресурс и не знаете конечную точку для его получения. PUT для других случаев. - person Portekoi; 19.07.2019

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

PUT    /items/1      #=> update
POST   /items        #=> create
person Tim Sullivan    schedule 10.03.2009
comment
POST /items добавляет новый элемент к уже определенному ресурсу («элемент»). Как сказано в ответе, это не создает группу. Я не понимаю, почему у него 12 голосов. - person David J.; 21.06.2012
comment
По умолчанию Rails не поддерживает «создание группы» через REST. Чтобы «создать группу», я имею в виду «создать ресурс», вы должны сделать это через исходный код. - person David J.; 21.06.2012
comment
У него 12 голосов, потому что оно предшествовало изменению, которое было внесено в группу. Я отменил изменение. - person Tim Sullivan; 21.06.2012
comment
Это справедливое указание, но чрезмерное упрощение. Как упоминается в других ответах, любой метод может использоваться как для создания, так и для обновления. - person Brad Koch; 07.03.2013
comment
Я согласен с ответом с небольшими изменениями. Используйте POST для создания и PUT для полного обновления ресурса. Для частичных обновлений мы можем использовать PUT или PATCH. Допустим, мы хотим обновить статус группы. Мы можем использовать PUT / groups / 1 / status со статусом - это полезная нагрузка запроса или PATCH / groups / 1 с подробностями о действии в полезной нагрузке. - person java_geek; 06.10.2014
comment
@BradKoch Вы правы с утверждением; но когда вы разрабатываете RESTful API, вам необходимо обеспечить его согласованность, чтобы облегчить жизнь клиентам, использующим ваши API. Если вы взаимозаменяемо используете POST / PUT для создания / обновления ресурсов, это усложняет жизнь вашему потребителю. Вы хотели бы, чтобы это было легко для ваших клиентов, потому что именно так вы увеличиваете свою потребительскую базу. - person java_geek; 06.10.2014
comment
Также должно быть ясно, что PUT /items/42 также действителен для создания ресурса, , но только если клиент имеет привилегию именовать ресурс. (Разрешает ли Rails клиенту эту привилегию именования?) - person DavidRR; 16.12.2014
comment
Красиво и коротко +1. Подробности читайте дальше :) - person Akif; 23.02.2021

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

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

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

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

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

person Jörg W Mittag    schedule 10.03.2009
comment
Нет ничего плохого в том, чтобы разрешить PUT создавать ресурсы. Просто имейте в виду, что это означает, что клиент предоставляет URL-адрес. - person Julian Reschke; 07.04.2010
comment
Что-то не так с разрешением PUT создавать ресурсы: клиент предоставляет URL-адрес. Это работа сервера! - person Joshcodes; 29.10.2013
comment
@Joshcodes Создание идентификаторов клиентов не всегда является задачей сервера. Я все чаще видел проекты, которые позволяют клиентам генерировать какой-то UUID в качестве идентификатора ресурса. Эта конструкция позволяет, в частности, увеличивать масштаб. - person Justin Ohms; 05.02.2017
comment
@JustinOhms Я согласен с вашей точкой зрения относительно идентификаторов, сгенерированных клиентом (примечание: все системы, разработанные мной примерно с 2008 года, требуют, чтобы клиент создавал идентификатор как UUID / Guid). Это не означает, что клиент должен указывать URL-адрес. - person Joshcodes; 06.02.2017
comment
@Joshcodes Это вопрос разделения проблем. То, где создается URL, на самом деле не имеет большого значения. Да, сервер отвечает за доставку контента с правильного URL-адреса, но это не ограничивает возможности сервера отвечать на запрос по неправильному URL-адресу. Правильный ответ от сервера в этом случае - 308. Правильный клиент затем попытается ввести PUT по правильному URL-адресу. Другой пример - распределенная система, в которой не все узлы знают обо всех ресурсах, предоставляемых клиентами. Здесь PUT для создания будет совершенно допустимым, потому что для этого серверного узла ресурс не существует. - person Justin Ohms; 06.02.2017
comment
@JustinOhms Я полностью согласен, это о разделении проблем. Я также согласен, что есть крайние случаи для использования PUT (недавно обнаруженный мной был связан с импортом данных, а не с возможностью повторного запуска). Подход, который вы описали выше, работает, потому что сервер инструктирует клиентов о том, как создавать соответствующие URI (слова Роя Филдинга). Однако для меня не очевидно, почему это лучше, чем просто использовать POST по назначению. - person Joshcodes; 06.02.2017
comment
@Joshcodes Причина использования такого PUT в настройке с несколькими узлами заключается в том, что для переключения клиента с PUT на POST клиенту потребуется знание о состоянии данных на этом узле. Это кажется странным, потому что мы часто думаем о сервере как о едином органе власти, однако в распределенной системе с конечной согласованностью клиент может фактически иметь больше информации, чем любой заданный серверный узел в любой момент времени. В этом случае клиент знает, что ресурс существует, а узел - нет. (возможно, необходима синхронизация) Плюс POST не подходит, потому что ресурс действительно существует. - person Justin Ohms; 07.02.2017
comment
Да, если ресурс уже существует, используйте PUT. Однако почти во всех случаях ресурсы должны создаваться с помощью POST, и клиент не должен предоставлять URL-адрес. Рой Филдинг согласен с этим заявлением FWIW: roy.gbiv. com / untangled / 2008 / rest-apis-must-be-hypertext-driven - person Joshcodes; 07.02.2017
comment
Любая ссылка с некоторыми комментариями Роя Филдинга? - person wlnirvana; 27.04.2020

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

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

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

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

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

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

  1. Клиент POST новый ресурс на сервер.
  2. Сервер обрабатывает запрос и отправляет ответ.
  3. Клиент никогда не получает ответа.
  4. Сервер не знает, что клиент не получил ответ.
  5. У клиента нет URL-адреса для ресурса (поэтому PUT не вариант) и повторяет POST.
  6. POST не идемпотентен, и сервер…

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

10.4.10 409 Конфликт

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

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

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

Ответ с кодом состояния 409 Conflict является правильным средством защиты, потому что:

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

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

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

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

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

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

person Joshcodes    schedule 29.10.2013
comment
Будет ли ответ 409 Conflict подходящим кодом для чего-то вроде попытки создать новую учетную запись с уже существующим именем пользователя? Я использовал 409 специально для конфликтов версий, но после прочтения вашего ответа мне интересно, не следует ли его использовать для каких-либо повторяющихся запросов. - person Eric B.; 09.07.2014
comment
@EricB. Да, в описанной вами ситуации из-за конфликта с текущим состоянием ресурса операция не выполняется. Кроме того, разумно ожидать, что пользователь сможет разрешить конфликт, и в теле сообщения нужно только сообщить пользователю, что имя пользователя уже существует. - person Joshcodes; 10.07.2014
comment
@Joshcodes, не могли бы вы рассказать больше о процессе разрешения конфликтов? В этом случае, если имя пользователя уже существует, ожидается ли, что клиент предложит конечному пользователю другое имя пользователя? Что, если клиент на самом деле пытается использовать POST для изменения имени пользователя? Следует ли по-прежнему использовать запросы PUT для обновления параметров, а POST - для создания объектов, будь то по одному или несколько? Спасибо. - person BFar; 23.01.2015
comment
@ BFar2, если имя пользователя уже существует, клиент должен запросить пользователя. Чтобы изменить имя пользователя, предполагая, что имя пользователя является частью уже созданного ресурса, который необходимо изменить, будет использоваться PUT, потому что вы правы, POST используется для создания, всегда и PUT для обновлений. - person Joshcodes; 23.01.2015
comment
объяснять вещи коротким и эффективным языком также является желательным навыком - person Junchen Liu; 24.08.2015
comment
@Joshcodes я ищу ответ на stackoverflow.com/questions/39057416/. комментирую сейчас, чтобы обратить на это ваше внимание. - person Roam; 20.08.2016
comment
@Joshcodes, я знаю, как игнорировать stackoverflow.com/questions/39057416/ не соответствуют архитектуре Restful. пока работает для нашего случая как исключение. - person Roam; 20.08.2016
comment
@Joshcodes Интересно. для пояснения: Выполнение POST данных, идентификатор которых соответствует ресурсу, уже находящемуся в системе, является конфликтом Разве не ваше предписание, что POST никогда не включает идентификатор, поскольку сервер определяет идентификатор? - person Iain; 24.09.2017
comment
Иэн, клиент определяет идентификатор. Сервер определяет URL. - person Joshcodes; 24.09.2017
comment
@Joshcodes Как клиент определяет ID? Создание UUID? А как насчет приложений, которые просто используют автоматически увеличивающийся идентификатор таблицы; что-то я много вижу. Это просто плохая практика? - person Kenmore; 25.02.2018
comment
@Zuko, На мой взгляд, автоинкрементным идентификаторам таблиц нет места в распределенной среде. UUID превосходят всех, кроме места для хранения. Интенты для идентификаторов - это пережиток того времени, когда хранение БД было более серьезной проблемой, чем сегодня. - person Joshcodes; 05.03.2018

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

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

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

Я интерпретирую это и требования идемпотентности к PUT так:

  • POST хорош для создания новых объектов в коллекции (и create не обязательно должно быть идемпотентным)
  • PUT хорош для обновления существующих объектов (и обновление должно быть идемпотентным)
  • POST также может использоваться для неидемпотентных обновлений существующих объектов (особенно для изменения части объекта без указания всего объекта целиком - если подумать, создание нового члена коллекции на самом деле является частным случаем такого рода обновление, с точки зрения коллекции)
  • PUT также можно использовать для создания, если и только если вы разрешаете клиенту называть ресурс. Но поскольку клиенты REST не должны делать предположений о структуре URL-адресов, это не соответствует предполагаемому духу вещей.
person metamatt    schedule 11.01.2012
comment
POST также может использоваться для неидемпотентных обновлений существующих объектов (особенно для изменения части объекта без указания всего объекта. Это то, для чего нужен PATCH - person Snuggs; 05.05.2012

Суммируя:

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

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

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

PUT Вы можете думать о том, что похоже на ОБНОВЛЕНИЕ СТУДЕНЧЕСКОГО НАБОРА address = abc, где id = 123;

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

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

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

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

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

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

person bharatj    schedule 29.07.2016
comment
для PUT аналогичен запросу INSERT или UPDATE - person Eugen Konkov; 22.08.2016
comment
на самом деле PUT Вы можете думать о том же, что и UPDATE STUDENT SET address = abc, где id = 123; будет заявлением для PATCH. ОБНОВЛЕНИЕ СТУДЕНЧЕСКОГО НАБОРА address = abc, name = newname, где id = 123 будет правильной аналогией для PUT - person mko; 12.04.2017
comment
Put также можно использовать для INSERT. Например, если сервер обнаружил, что вы пытаетесь загрузить один и тот же файл несколько раз, это сделает ваш запрос идемпотентным. (Загрузка новых файлов не производится). - person kiwicomb123; 21.08.2018

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

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

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

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

POST против PUT

person Homer6    schedule 14.06.2013
comment
Нет, PUT означает, что вы знаете URL. Если вы знаете только идентификатор, выполните POST с этим идентификатором, чтобы получить URL. - person Joshcodes; 29.10.2013
comment
Идентификатор является частью URL-адреса, поэтому да, используйте PUT, если вы знаете URL-адрес (который включает идентификатор). - person Homer6; 30.10.2013
comment
Нет, URL-адрес определяется сервером, и идентификатор не обязательно является частью URL-адреса. Рой Филдинг сказал бы вам, что то же самое или вы можете просто прочитать его тезис. - person Joshcodes; 30.10.2013
comment
@Joshcodes, это предполагает ОТДЫХ? В архитектуре RESTful идентификатор элемента определенно является частью URL-адреса, например: / people / 123. Мне нравится этот сайт для REST: microformats.org/wiki/rest/urls - person Beez; 26.12.2013
comment
@Beez ссылка mircoformats предлагает хороший способ для серверов структурировать свои URL-адреса, но server определяет URL. Клиент, которого почти никогда не будет, делает. См. мой ответ или связанный article, если вы этого не понимаете. - person Joshcodes; 07.01.2014
comment
@Joshcodes, я не отрицаю, где определяется URL. Я говорю, что в архитектуре RESTful (определяемой с сервера) идентификатор является частью URL-адреса. - person Beez; 08.01.2014
comment
@Beez, если сервер определяет URL-адрес, URL-адрес не должен диктоваться клиентом. Поэтому, даже если вы знаете идентификатор, используйте POST, а не PUT. Должен ли идентификатор быть частью URL-адреса - это другой разговор. - person Joshcodes; 08.01.2014
comment
Я думаю, что Общее правило охватывает это, как правило, с идентификатором или именем в URL-адресе. Отличный ответ! - person TamusJRoyce; 11.05.2015
comment
@TamusJRoyce, Рой Филдинг (парень, создавший REST) ​​не согласился бы с вами: roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertext-driven Кроме того, хотя это правда, что идентификатор, скорее всего, будет предоставлен клиентом через URL-адрес, который клиент все еще не знает, где в URL поместить идентификатор. - person Joshcodes; 11.09.2015
comment
@beez и Homer6: Joshcodes верен. Ничто в REST не требует, чтобы идентификатор был в URL-адресе, а URL-адрес со структурой типа / collection /: id не означает, что веб-сайт является RESTful. Фактически, сайты с не-HTML-представлениями почти всегда таковыми не являются. - person Nicholas Shanks; 26.12.2016

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

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

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

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

POST x: «Сохраните мой контент и дайте мне идентификатор, который я могу использовать для идентификации ресурса (старого или нового), содержащего указанный контент (возможно, смешанный с другим контентом). Указанный ресурс должен быть идентичен или подчинен тому, который идентифицирует x». «Ресурс y подчиняется ресурсу x» обычно, но не обязательно, реализуется путем превращения y в подпуть 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, когда закончите."

person Jordan    schedule 01.08.2012
comment
Но как вы можете использовать PUT для создания нового ресурса, если он не существует, в то время как ваш метод генерации идентификатора находится в режиме автоматического увеличения? Обычно ORM автоматически генерирует идентификатор для вас, например, так, как вы хотите, чтобы он был в POST. Означает ли это, что если вы хотите правильно реализовать PUT, вам нужно изменить автогенерацию идентификатора? Это неудобно, если ответ положительный. - person Roni Axelrad; 16.09.2018
comment
@RoniAxelrad: PUT похож на оператор INSERT OR UPDATE базы данных, где вы включаете ключ в оператор, поэтому применимо только там, где вы можете гарантировать отсутствие коллизий. например. у вашего домена есть «естественный ключ» или вы используете гид. POST похож на вставку в таблицу с автоматически увеличивающимся ключом. База данных должна сообщить вам, какой ID она получила после того, как была вставлена. Обратите внимание, что ваш INSERT OR UPDATE заменит любые предыдущие данные, если они существовали. - person Nigel Thorne; 26.11.2018
comment
@NigelThorne Спасибо за ответ. Итак, если, например, я пытаюсь ПОСТАВИТЬ книгу с идентификатором 10 с URI: PUT books / 10. Если книги с идентификатором 10 не существует, я должен создать книгу с идентификатором 10, верно? но я не могу контролировать числитель идентификатора создания, потому что он автоматически увеличивается. что мне делать в этой ситуации? - person Roni Axelrad; 27.11.2018
comment
@RoniAxelrad REST PUT к несуществующему идентификатору - это запрос к серверу на создание ресурса. Сервер все еще должен решить, хочет ли он это разрешить. Сервер отвечает. Он может ответить «Нет». Я не буду этого делать. Вы уже делаете это, если у пользователя недостаточно прав ... и т. Д. Сервер может сказать Нет. REST - это соглашение, которое позволяет нам определять значение различных типов запросов ... ваш сервер решает, что делать с этими запросами, на основе вашей бизнес-логики :) Даже если он говорит нет, он все равно после ОТДЫХА :) - person Nigel Thorne; 03.12.2018

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

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

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

ПОЧТА:

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

ПОЛОЖИЛ:

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

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

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

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

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

person ishandutta2007    schedule 15.10.2017
comment
Ваш короткий ответ может быть ОЧЕНЬ неправильным. HTTP PUT может повторяться HTTP-прокси. Итак, если PUT на самом деле выполняет SQL INSERT, он может потерпеть неудачу во второй раз, что означает, что он вернет другой результат, и поэтому он не будет IDEMPOTENT (в этом разница между PUT и POST) - person Kamil Tomšík; 30.04.2018

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

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

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

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

person germanlinux    schedule 26.02.2012

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

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

person skillet-thief    schedule 25.03.2011
comment
Я немного опоздал с этим, но кто-то сказал что-то подобное на другом веб-сайте, и это заставило меня щелкнуть. Если вы создаете ресурс и используете автоматически увеличивающийся идентификатор в качестве идентификатора вместо имени, назначенного пользователем, это должен быть POST. - person Ixmatus; 03.02.2012
comment
Это не совсем правильно - PUT все еще может создавать ресурс, ссылаясь на него с неканоническим именем, пока в ответе сервер возвращает заголовок Location, который действительно содержит канонический ресурс. имя. - person Ether; 19.10.2012
comment
@Joshcodes не забывайте, что у вас может быть много URI, ссылающихся на один и тот же базовый ресурс. Итак, то, что сказал эфир, является разумным советом, клиент может ПОСТАВИТЬ на URL-адрес (который может быть более семантическим, например PUT /X-files/series/4/episodes/max), а сервер отвечает URI, который предоставляет короткую каноническую уникальную ссылку на этот новый ресурс (например, /X-Ffiles/episodes/91) - person thecoshman; 08.06.2015
comment
@thecoshman проблема в том, что структура URL-адреса не принадлежит клиенту. Прочитав о самопознании (также являющемся частью REST), вы сможете прояснить это. - person Joshcodes; 08.06.2015
comment
@Joshcodes, то по этой логике клиент никогда не должен использовать PUT для создания, поскольку он не должен беспокоиться о предоставлении URL-адреса. Что ж ... если сервер не предоставил URL-адрес для PUT, если клиент хочет поместить его ... что-то вроде PUT / comments / new, и сервер может ответить 204 / comments / 234532, но мне это кажется немного RPC, клиент должен просто отправить сообщение / комментарии ... - person thecoshman; 09.06.2015
comment
@thecoshman да, клиент действительно никогда не должен использовать PUT. Что в этом RPC? - person Joshcodes; 10.06.2015
comment
@thecoshman: нет, вы не можете иметь несколько URL-адресов, указывающих на один ресурс. Каждый уникальный URI - это уникальный ресурс, и каждый ресурс имеет один и только один URI. - person Nicholas Shanks; 26.12.2016
comment
@NicholasShanks, не совсем. Рассмотрим ресурс, который представляет школьного ученика, вы можете получить доступ к /student/123, но вы также можете получить доступ к тому же ученику через /class/abc/student/123. Это совершенно верно. Однако существует концепция канонического URI, который в данном случае можно назвать первым. Буква U означает «Единообразие», а не «Уникальность». - person thecoshman; 09.01.2017
comment
@thecoshman Тогда у вас будет два идентичных ресурса, которые просто меняются каждый раз, когда это делает другой. Хотя ссылка от одного к другому с отношением canonical определенно поможет. Даже если вы предоставили заголовок Content-Location с одним, указывающим на путь к другому, это не объединит базовые ресурсы, представленные каждым URL-адресом. Учтите, что представление не является ресурсом, и два идентичных представления не создают один и тот же ресурс (например, downloads / v1.0.0 / и downloads / latest-version /) - person Nicholas Shanks; 09.01.2017
comment
@NicholasShanks Я думаю, что этот ответ дает хорошее объяснение, с которым я согласен, но также учитываю вашу точку зрения. Я бы также сказал, что это, наверное, более подходящее место для этой дискуссии. - person thecoshman; 09.01.2017

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

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

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

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

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

person UniCoder    schedule 14.02.2017
comment
Если комментарий является объектом со свойством, например идентификатором пользователя, датой создания, сообщением-комментарием и т. Д., И во время редактирования обновляется только сообщение-комментарий, здесь следует выполнить ПАТЧ? - person Mohammed H; 12.08.2017
comment
PUT используется FB для обновления комментария, потому что существующий ресурс обновляется, и это то, что делает PUT (обновляет ресурс). PUT, в отличие от POST, идемпотентен. Идемпотентность HTTP-глагола влияет на обработку ошибок, но не требует использования. См. Мой ответ для более подробного объяснения: stackoverflow.com/questions/630453/put-vs-post-in-rest/ - person Joshcodes; 19.06.2018

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

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

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

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

  • POST делает недействительными кэшированные копии всего содержащего ресурса (лучшая согласованность)
  • Ответы PUT не кэшируются, в то время как ответы POST (требуется Content-Location и срок действия)
  • PUT менее поддерживается, например, Java ME, старые браузеры, брандмауэры
person Hans Malherbe    schedule 08.02.2012
comment
Это неверно. Для POST состояние также не определено только до первой успешной повторной попытки. Затем сервер принимает POST (сообщение так и не пришло), генерирует конфликт 409 для повторяющегося идентификатора (сообщение прибыло, ответ был потерян) или любой другой допустимый ответ. - person Joshcodes; 24.04.2014
comment
В общем случае агент пользователя не сможет безопасно повторить попытку POST, поскольку операция POST не дает гарантии того, что две операции будут иметь тот же эффект, что и одна. Термин ID не имеет ничего общего с HTTP. URI идентифицирует ресурс. - person Hans Malherbe; 25.07.2014
comment
Агент пользователя может безопасно повторять операцию POST столько раз, сколько захочет. Он просто получит ошибку повторяющегося идентификатора (при условии, что у ресурса есть идентификатор) или ошибку повторяющихся данных (при условии, что это проблема, а у ресурса нет идентификаторов). - person Joshcodes; 27.07.2014
comment
Бьет головой о стену. HTTP не имеет решения проблемы надежности, и это плохо понимается, мало обсуждается и просто не обслуживается в подавляющем большинстве веб-приложений. @Joshcodes У меня есть ответ на этот вопрос. По сути, я согласен с Гансом. Есть проблема. - person bbsimonbb; 13.06.2018
comment
@bbsimonbb, HTTP имеет надежный и хорошо документированный набор сообщений об ошибках. Мой ответ на этот вопрос (stackoverflow.com / questions / 630453 / put-vs-post-in-rest /) описывает, как использовать http в соответствии со спецификацией для достижения согласованности. - person Joshcodes; 19.06.2018
comment
делает недействительными кэшированные копии всего содержащего ресурса любую ссылку на это? Кроме того, браузеру никогда не обязательно следовать установленным правилам кеширования. - person Honey; 26.11.2018

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

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

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

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

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

ИЗМЕНИТЬ

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

Это означает, что если вам нужно отправить

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

вам следует использовать метод POST

person Rohit Dhiman    schedule 25.09.2018
comment
Почему за это не проголосовали? Если это правда, это критическое различие, не так ли? - person Iofacture; 29.09.2018
comment
Я столкнулся с этим при реализации API для обновления профиля, которое включает загрузку картинки профиля пользователя. Затем я протестировал его с помощью почтальона, Ajax, PHP curl и laravel 5.6 в качестве бэкэнда. - person Rohit Dhiman; 29.09.2018

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

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

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

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

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

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

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

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

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

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

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

person bbsimonbb    schedule 18.02.2016
comment
Разве сохранение ответа не похоже на поддержание сеанса? Это вызовет проблемы с (горизонтальным) масштабированием. - person Saurabh Harwande; 21.08.2018

Кажется, всегда существует некоторая путаница относительно того, когда использовать 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 не идемпотентным. То есть операция является идемпотентной, если она может выполняться с ресурсом один или несколько раз и всегда возвращать одно и то же состояние этого ресурса. В то время как неидемпотентная операция может возвращать измененное состояние ресурса от одного запроса к другому. Следовательно, в неидемпотентной операции нет гарантии, что будет получено такое же состояние ресурса.

Основываясь на приведенном выше определении идемпотента, я предлагаю использовать метод 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.

person Burhan    schedule 10.10.2013
comment
Update = ›HTTP POST: POST не предназначен для обновления - person Premraj; 30.01.2016
comment
@premraj Вы сделали предположение, что Бурхан говорит вам не делать этого; а именно, вы объединяете CRUD, REST и HTTP. Если вы прочитаете RFC 7231, где эти вещи определены, вы обнаружите, что в протоколе HTTP определение POST, безусловно, допускает обновление. Только ограничения REST говорят об обратном. - person IAM_AL_X; 16.04.2020

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

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

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

person inf3rno    schedule 16.01.2014
comment
Думаю, вам удалось предоставить один из немногих хороших примеров использования PUT, молодец. - person thecoshman; 08.06.2015

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

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

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


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

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

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


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

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

person Gerard ONeill    schedule 21.10.2013

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

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

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

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

Например, если вы хотите создать новый поток, вы можете ПОСТАВИТЬ его на какой-нибудь URL. Но если вы хотите отправить сообщение в существующий поток, вы отправляете сообщение на его URL-адрес.

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

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

person Gregory Magarshak    schedule 23.10.2011
comment
То, что вы описываете POST, - это то, как на самом деле должен себя вести PATCH. POST должен означать что-то более похожее на добавление сообщения в список рассылки. - person Alexander Torstling; 28.11.2014

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

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

Например:

  • POST / шт.
  • PUT / items / 1234

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

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

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

person tothemario    schedule 21.06.2017

Вот простое правило:

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

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

person Adam Griffiths    schedule 11.12.2013
comment
PUT не для обновления, это для замены, обратите внимание, что для создания вы ничего не заменяете чем-то. POST абсолютно не предназначен для обновления в любой форме. - person thecoshman; 08.06.2015
comment
Об этом говорится в спецификации http? Или вы основываете свой комментарий на другом? - person Adam Griffiths; 10.07.2016
comment
Это просто здравый смысл, как вы что-то обновляете, когда не знаете, что именно вы обновляете? POST предназначен для создания нового ресурса. - person thecoshman; 27.07.2016
comment
thecoshman - здесь вы злоупотребляете семантикой - замена может быть обновлением, если это тот же ресурс с некоторыми отличиями. Замена действительна для размещения только в том случае, если замена используется для изменения того же ресурса. Замена новым и другим ресурсом недопустима (удалить старый и добавить новый?), Особенно если «новый» ресурс не имеет естественного идентификатора. POST, OTOH, - это то, что может создавать, обновлять, заменять и удалять - использование публикации зависит от того, есть ли сообщение для интерпретации, такое как `` применить скидку '', которое может или не может изменить ресурс в зависимости от логика. - person Gerard ONeill; 28.12.2016
comment
Что касается вашего второго комментария - как насчет того, чтобы «получить» ресурс, изменить поля, которые вам нужны, а затем вернуть его? Или как насчет того, чтобы ресурс поступил из другого источника, но использует естественный идентификатор (внешний идентификатор) - put, естественно, обновит ресурс по URL-адресу при изменении исходных данных. - person Gerard ONeill; 28.12.2016

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

  1. Выбирать
  2. Вставлять
  3. Обновлять
  4. Удалить
  5. Объединить (обновить, если уже существует, иначе вставить)

Я использую PUT для операций слияния и обновления, а также POST для вставок.

person Rajan    schedule 29.06.2016

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

Давайте будем очень ясными и прямыми. Если вы разработчик .NET, работающий с веб-API, факты (из документации Microsoft API) следующие: http://www.asp.net/web-api/overview/creating-web-apis/create-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.

person Tom Stickel    schedule 21.07.2014

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

person java_geek    schedule 06.10.2014
comment
По большей части, прочитав весь этот шум, вы, кажется, на высоте. Я бы сказал, что мы должны называть PUT методом замены, а не создавать / обновлять. Я думаю, что он лучше описывает то, что он делает. - person thecoshman; 08.06.2015

POST: используйте его для создания новых ресурсов. Это похоже на INSERT (оператор SQL) с автоматически увеличивающимся идентификатором. В ответной части он содержит новый сгенерированный идентификатор.

POST также используется для обновления записи.

PUT: используйте его для создания нового ресурса, но здесь я знаю идентификационный ключ. Это похоже на INSERT (оператор SQL), где я заранее знаю идентификационный ключ. В ответной части он ничего не отправляет.

PUT также используется для обновления ресурса

person sushil pandey    schedule 12.12.2013
comment
PUT не для обновления, это для замены, обратите внимание, что для создания вы ничего не заменяете чем-то. POST абсолютно не предназначен для обновления в любой форме. - person thecoshman; 08.06.2015

Методы запроса GET, PUT и DELETE являются операциями управления данными низкого уровня (см. RFC 7231, § 4.3.1, § 4.3.4 и § 4.3.5 ), т.е. операции CRUD (создание, чтение, обновление и удаление), на состояние ресурса target (идентифицируемого URI запроса):

  • GET должен читать представление о состоянии целевого ресурса;
  • PUT должен создать или обновить состояние целевого ресурса с помощью представления запроса;
  • DELETE должен удалить состояние целевого ресурса.

Напротив, метод запроса POST - это операция обработки высокого уровня (см. RFC 7231, § 4.3.3), то есть не-CRUD операция. POST должен обрабатывать представление запроса. Обработка может создать состояние ресурса, но для ресурса, отличного от целевого ресурса. Он не должен создавать или обновлять состояние целевого ресурса с помощью представления запроса, потому что для этого сделана более конкретная операция CRUD PUT, как объяснил Рой Филдинг в своей статье блога Можно использовать POST:

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

Таким образом, фундаментальное различие между операциями CRUD (GET, PUT и DELETE в HTTP) и операциями без CRUD (POST в HTTP) заключается в уровне абстракции. Алан Кей говорил об этой разнице в контексте объектно-ориентированного программирования в большинстве своих выступлений и в своей статье по ACM Ранняя история Smalltalk (выделено мной):

Что я получил от Simula, так это то, что теперь вы можете заменить привязки и назначения целями. Последнее, что вы хотели бы от любого программиста, - это возиться с внутренним состоянием, даже если оно представлено образно. Вместо этого объекты должны быть представлены как сайты более высокого уровня поведения, более подходящие для использования в качестве динамических компонентов.

[…] К сожалению, большая часть того, что сегодня называют объектно-ориентированным программированием, представляет собой простое программирование в старом стиле с более причудливыми конструкциями. Многие программы загружены операциями в стиле присваивания, которые теперь выполняются более дорогими присоединенными процедурами.

[…] Заявления о назначении - даже абстрактные - выражают очень низкоуровневые цели, и для выполнения чего-либо потребуется их больше. […] Еще один способ подумать обо всем этом: хотя позднее связывание автоматического выделения памяти не делает ничего такого, что не может сделать программист, его присутствие приводит как к более простому, так и к более мощному коду. ООП - это стратегия позднего связывания для многих вещей, и все они вместе сдерживают хрупкость и рост размеров намного дольше, чем старые методологии.

person Maggyero    schedule 04.12.2020

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

Вы должны использовать PATCH. Вы ПАТЧИВАЕТЕ список вопросов вроде

PATCH /questions HTTP/1.1

со списком, содержащим ваш объект, который будет создан, например

[
    {
        "title": "I said semantics!",
        "content": "Is this serious?",
        "answer": "Not really"
    }
]

Это запрос PATCH как

  • вы изменяете существующий список ресурсов , не предоставляя полностью новый контент
  • вы меняете состояние своего нового вопроса с несуществующего на существующий без предоставления всех данных (сервер, скорее всего, добавит id).

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

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

Недостатком является то, что, вероятно, никто не использует PATCH таким образом. Боюсь, это я только что придумал, но надеюсь, что дал хорошую аргументацию.

Вместо этого вы можете использовать CREATE, поскольку пользовательские HTTP-команды разрешены, просто они могут не работать с некоторыми инструментами.

Что касается семантики, CREATE - ИМХО единственный правильный выбор, все остальное - квадратный колышек в круглое отверстие. К сожалению, все, что у нас есть, - это круглые дырочки.

person maaartinus    schedule 08.05.2018
comment
Я думаю, вам следует быть осторожным, заявляя, что PATCH следует использовать, не предоставляя некоторых поясняющих заявлений. PATCH отлично подходит для обновления ресурсов, но не предназначен для создания ресурсов. В спецификациях HTTP специально указано, что это только для обновления ресурсов. Вы можете заставить работать что угодно, как вы заявили, но глаголы теряют свое значение, когда вы произвольно наделяете их нестандартными функциями. - person Jitsusama; 02.07.2019
comment
@Jitsusama Прочтите мое предпоследнее предложение ... и, возможно, погуглите для этого. Это похоже на попытку взломать парадигму программирования из контрольных битов заголовка TCP-пакета! Если URG высокий, то моя встреча по календарю очень важна. Если ACK низкий, я отклоняю ваш запрос на добавление в друзья. - person maaartinus; 03.07.2019
comment
Я думаю, это плохая идея. По сути, если вы говорите, что вставка в список - это патч, патчем становится все: вставка, обновление и даже удаление. Это не решает проблемы, но фактически добавляет еще одну двусмысленность. - person dariok; 25.10.2019
comment
@dariok Согласен, было бы еще хуже, чем сейчас. - person maaartinus; 26.10.2019

Я думаю, что есть также интересный момент, о котором не говорили в этом вопросе PUT vs POST:

Если вы хотите иметь веб-приложение, которое работает без JavaScript (например, если кто-то использует браузер командной строки, такой как Lynx, или надстройку браузера, например NoScript или uMatrix), вам придется использовать POST для отправки данных, поскольку формы HTML поддерживают только HTTP-запросы GET и POST.

Обычно, если вы хотите использовать прогрессивное улучшение (https://en.wikipedia.org/wiki/Progressive_enhancement), чтобы ваше веб-приложение работало везде, с JavaScript и без него, вы не можете использовать другие HTTP-методы, такие как PUT или DELETE, которые были добавлены только в HTTP версии 1.1.

person baptx    schedule 26.06.2019

Дополнение ко всем ответам выше:


Чаще всего используется в профессиональной практике,


  • мы используем PUT вместо POST в операции CREATE. Почему? потому что многие здесь также сказали, что ответы не кэшируются, в то время как ответы POST (Требовать Content-Location и срок действия).
  • Мы используем POST поверх PUT в операции UPDATE. Почему? потому что он делает недействительными кэшированные копии всего содержащего ресурса. что полезно при обновлении ресурсов.
person Md. Tazbir Ur Rahman Bhuiyan    schedule 20.09.2019