Прежде всего, некоторые определения:
PUT определяется в Раздел 9.6 RFC 2616:
Метод PUT запрашивает, чтобы закрытый объект хранился в запрошенном Request-URI. Если Request-URI ссылается на уже существующий ресурс, закрытый объект СЛЕДУЕТ считаться измененной версией той, которая находится на сервере происхождения. Если Request-URI не указывает на существующий ресурс и что URI может быть определен как новый ресурс запрашивающим пользовательским агентом, исходный сервер может создать ресурс с этим URI.
PATCH определяется в RFC 5789:
Метод PATCH запрашивает набор изменений, описанный в объект запроса применяется к ресурсу, идентифицированному Request- URI.
Также согласно RFC 2616 Раздел 9.1.2 PUT является Idempotent, в то время как PATCH не является.
Теперь давайте взглянем на реальный пример. Когда я делаю POST до /users
с данными {username: 'skwee357', email: '[email protected]'}
, и сервер способен создать ресурс, он ответит на 201 и местоположение ресурса (допустим /users/1
), и любой следующий вызов GET /users/1
вернется {id: 1, username: 'skwee357', email: '[email protected]'}
.
Теперь скажем, я хочу изменить свою электронную почту. Модификация электронной почты считается "набором изменений", и поэтому я должен PATCH /users/1
с "патч-документом". В моем случае это будет json {email: '[email protected]'}
. Затем сервер возвращает 200 (при условии, что разрешение одобрено). Это подводит меня к первому вопросу:
- PATCH НЕ Идемпотент. Он так сказал в RFC 2616 и RFC 5789. Однако, если я выдам тот же запрос PATCH (с моим новым электронным письмом), я получаю одно и то же состояние ресурса (с изменением моего адреса электронной почты до требуемого значения). Почему PATCH не является идемпотентным?
PATCH - относительно новый глагол (RFC, введенный в марте 2010 года), и он решает проблему "исправления" или изменения набора полей. Перед введением PATCH каждый использовал PUT для обновления ресурса. Но после того, как PATCH был представлен, он оставляет меня в замешательстве, что для этого используется PUT? И это подводит меня к второму (и главному) вопросу:
- Какая разница между PUT и PATCH? Я где-то читал, что PUT может использоваться для заменять весь объект под определенным ресурсом, поэтому нужно отправить полный объект (вместо набора атрибутов, как в PATCH). Какое реальное практическое применение для такого случая? Когда вы хотите заменить/перезаписать объект под определенным URI ресурса и почему такая операция не рассматривается как обновление/исправление объекта? Единственный практический случай, который я вижу для PUT, - это выпуск PUT для коллекции, т.е.
/users
для замены всей коллекции. Выдача PUT на определенном объекте не имеет смысла после введения PATCH. Я не прав?