Вы правы, указывая на то, что в протоколе HTTP нет ничего неотъемлемого, что обеспечивает идемпотентный атрибут методов/глаголов, таких как PUT
и DELETE
. HTTP, будучи протоколом без сохранения состояния, не сохраняет никакой информации или статуса каждого запроса, который делает пользователь. ; каждый отдельный запрос рассматривается как независимый.
Процитируем Википедию по поводу идемпотентного атрибута HTTP-методов (выделено мной):
Обратите внимание, что идемпотентность метода не зависит от протокола или веб-сервера. Вполне возможно написать веб-приложение, в котором (например) вставка в базу данных или другое неидемпотентное действие запускается GET или другим запросом. Однако игнорирование этой рекомендации может привести к нежелательным последствиям, если пользовательский агент предполагает, что повторение одного и того же запроса безопасно, хотя это не так.
Так что да, можно отклоняться от обычной реализации и развертывать такие вещи, как неизменяемая реализация POST, неидемпотентный PUT и т. д., вероятно, без значительных, опасных для жизни технических проблем. Но вы рискуете расстроить других программистов, использующих ваши веб-сервисы, думая, что вы не знаете, что делаете.
Вот важная цитата из RFC2616 о методах HTTP, безопасно (выделено мной):
Разработчики должны знать, что программное обеспечение представляет пользователя в их взаимодействиях через Интернет, и должны быть осторожны, чтобы позволить пользователю знать о любых действиях, которые они могут предпринять, которые могут иметь неожиданное значение для них самих или других.
В частности, было установлено соглашение о том, что методы GET и HEAD НЕ ДОЛЖНЫ иметь значения выполнения каких-либо действий, кроме извлечения. Эти методы следует считать «безопасными». Это позволяет пользовательским агентам представлять другие методы, такие как POST, PUT и DELETE, особым образом, чтобы пользователь знал о том, что запрашивается возможно небезопасное действие.
Естественно, невозможно гарантировать, что сервер не будет генерировать побочные эффекты в результате выполнения GET-запроса; на самом деле, некоторые динамические ресурсы считают это функцией. Важным отличием здесь является то, что пользователь не запрашивал побочные эффекты, поэтому не может нести за них ответственность.
ОБНОВЛЕНИЕ: как указал Джулиан, RFC 2616 был заменен RFC 7231. Вот соответствующий раздел.
Итак, когда вы публикуете веб-сервис как метод PUT
, и я отправляю запрос, который выглядит так:
PUT /users/<new_id> HTTP/1.1
Host: example.com
Я ожидаю, что будет создан новый пользовательский ресурс. Аналогично, если мой запрос выглядит так:
PUT /users/<existing_id> HTTP/1.1
Host: example.com
Я ожидаю, что соответствующий существующий пользователь будет обновлен. Если я повторяю один и тот же запрос, отправляя форму несколько раз, пожалуйста, не выводит диалоговое окно с предупреждением (потому что мне нравится установленное соглашение).
И наоборот, как потребитель веб-службы POST, я буду ожидать таких запросов, как:
POST /users/<existing_id> HTTP/1.1
Host: example.com
для обновления соответствующего существующего пользователя, а запрос выглядит так:
POST /users/<new_id> HTTP/1.1
Host: example.com
чтобы вызвать ошибку, потому что URL-адрес еще не существует.
person
ivan.sim
schedule
01.01.2015