Привет.
Стыдно признаться, но я прочитав много различных статей, все равно не до конца осознаю разницу между 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, т.к. все равно все случаи применения апи не покроешь именами методов рекомендуемыми спецификацией протокола.
Комментариев нет:
Отправить комментарий