Страницы

Поиск по вопросам

воскресенье, 24 ноября 2019 г.

Разница между PUT и POST


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

Спецификация HTTP 1.1 гласит, что PUT
идемпотентен. Это значит, что клиент
может выполнить множество PUT запросов
по одному URI и это не приведет к
созданию записей дубликатов. Операции
присвоения — хороший пример
идемпотентной операции
String userId =
this.request["USER_ID"];
Даже если эту операцию выполнить
дважды или трижды, никакого вреда не
будет (кроме лишних тактов
процессора). POST же с другой стороны
не идемпотентен. Это что-то вроде
инкремента. Вам следует использовать
POST или PUT с учетом того является ли
выполняемое действие идемпотентным или
нет. Говоря языком программистов, если
клиент знает URL объекта, который
нужно создать, используйте PUT. Если
клиент знает URL метода/класса
создающего нужный объект, используйте
POST.

Здесь приведен "хороший пример идемпотентной операции String userId = this.request["USER_ID"];". 
В чем пример хороший не пойму? Какой вред может быть от этой операции если мы используем POST а не PUT?
Был бы очень признателен, если бы мне дали простой пример, где лучше применять PUT и почему.
Например огромное число сервисов для загрузки файлов использует PUT. Чем это оправдано?
Меня интересует в частности загрузка файлов.    


Ответы

Ответ 1



Разница между PUT и POST - это вопрос семантики. Коль скоро для операций используются разные глаголы, то и смысл у них должен быть разным. Представьте, что ваш сервис оперирует понятиями блокнот (notebook) и запись (post). Один блокнот может содержать множество записей. Для добавления новой записи в блокнот c идентификатором id вы будете использоват метод POST с URL mydomain/notebooks/id/. Ваш сервис, ориентируясь на метод POST, са присвоит нужный идентификатор записи, добавит ее в блокнот и вернет вам URL созданной записи (для доступа к записи по GET или для удаления по DELETE). При этом хорошо бы вернуть клиенту URL созданной записи. Допустим, запись с идентификатором post-id уже создана и доступна по URL mydomain/notebooks/id/posts/post-id Но клиент (владелец записи) исправил в ней ошибку и хочет перезаписать ее. Для этог он использует метод PUT с URL mydomain/notebooks/id/posts/post-id и передает обновленную запись в теле запроса. Ваш сервис, ориентируясь на метод PUT удаляет старую запись и записывает новую, при этом она доступна по тому же URL. Конечно, никто не мешает вам всегда использовать метод POST (например HTML 4 позволя использовать только методы GET и POST). Но все же стоит придерживаться рекомендаций в целях единообразной трактовки методов всеми разработчиками. UPD: Вспомнил еще кое-что. Рекомендуется использоваться метод POST для создания подчиненног ресурса (дочернего по отношению к другому ресурсу; пример блокнота и записи как раз очень подходит).

Ответ 2



Насколько я понимаю все это, то, если сравнить PUT и POST операциями в MySQL, т POST - это INSERT, а PUT - UPDATE or INSERT by KES Расмотрим на примере форума. В нём есть темы и сообщения. Мы делаем запросы в тему hello POST /topic/hello?message = Здесь POST /topic/hello?message = был POST /topic/hello?message = Вася Первый запрос создаст (INSERT) тему hello с сообщением "Здесь", остальные два запрос тоже создадут (INSERT) новые сообщения в теме. В результате у нас получится, что тема hello содержит: Здесь был Вася. PUT /topic/hello?message = Здесь PUT /topic/hello?message = был PUT /topic/hello?message = Вася Первый запрос создаст (INSERT) тему hello с сообщением "Здесь", остальные два запрос обновят (UPDATE) сообщение в теме. В результате у нас получится, что тема hello содержит: Вася. Идемпотентность PUT здесь проявляется в том, что количество сообщений в базе пр последующих операциях остаётся неизменным. Касательно ссылок - карта сайта будет оставаться неизменной. Будет обновляться лишь содержимое тем. или: каждый запрос POST /article/hello будет создавать новую главу в статье hello. Первый запрос создаст саму статью. каждый запрос PUT /article/hello будет обновлять ЕДИНСТВЕННУЮ главу в статье hello. Первый запрос создаст саму статью. Вот, что нам должен возвращать GET, если мы делали POST GET /topic/hello 201 Здесь был Вася В этом случае у нас также будут доступны и эти URI GET /topic/hello/1 201 Здесь GET /topic/hello/2 201 был GET /topic/hello/3 201 Вася Вот, что нам должен вернуть GET, если мы делали PUT GET /topic/hello 201 Вася В этом случае у нас будет доступна только одна URI GET /topic/hello/1 201 Вася GET /topic/hello/2 404 GET /topic/hello/3 404 EXAMPLE #2 Пример с пользователями. POST /user/eugen?age=7 POST /user/eugen?age=10 POST /user/eugen?age=5 Создаст 3 пользователя с именем eugen и возрастом 7, 10, 5, соответственно. PUT /user/eugen?age=7 PUT /user/eugen?age=10 PUT /user/eugen?age=5 Будет создан только один пользователь с именем eugen с возрастом 5 Другими словами: PUT обязан обновлять запись, если данные уже есть Отсюда и Ваш пример String userId = this.request["USER_ID"]; с сохранением значени в переменной. Сколько раз вы бы не ложили (PUT) значения в переменную - переменная всегда будет одна. Отсюда родился EXAMPLE #3 Не знаю на сколько эта аналогия верна, но думаю это утверждение будет верно: POST: push $variable, value; -- в итоге массив значений PUT: $variable = value; -- в итоге одно значение в случае POST, вред, который может возникнут, это переполнится память сервера. случае PUT - никакого вреда нет, только такты забираются ;-) Кстати, вот нашел хороший ресурс, по поводу безопасности и идемпотентности http://restcookbook.com/HTTP%20Methods/idempotency/

Ответ 3



Создаст 3 пользователя с именем eugen и возрастом 7, 10, 5, соответственно. PUT /user/eugen?age=7 PUT /user/eugen?age=10 PUT /user/eugen?age=5 Мне кажется это не правильно спроектированное Api , Put - должен быть идемпотенте , но при создании api обычно возвращает 201 код а при Update 200 т.ё. create/update нельзя делать put. IMHO Post<=> Create/Update Put<=> Update И семантически PUT /user/eugen?age=7 - установить евгену возраст 7 а ни как не создать 7-ми летнего Евгена. Тогда http ответ должен быть либо 404 если евген не найден либо 200 если всё удачно поапдейтилось.

Ответ 4



Насколько я понимаю, это обычно используется для api, скажем делаем PUT на url http://rest.mysite.com/documents/balance_201 , как следует из семантики мы создаем документ если его нет, если есть, то выдаем ошибку при POST документ обновится, если есть, а если нет - ошибка, но в современном мире всеми этими вещами управляет логика основанная не на url а на содержании пакета, так, что я лично предпочитаю api основанные на POST, т.к. все равно все случаи применения апи не покроешь именами методов рекомендуемыми спецификацией протокола.

Комментариев нет:

Отправить комментарий