Подтвердить что ты не робот

Почему HTTP PUT не разрешает выполнять частичные обновления в REST API?

Кто сказал, что API RESTful должен поддерживать частичные обновления отдельно через HTTP PATCH?

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

Я задаю этот вопрос в контексте создания REST API с HTTP, который обеспечивает абстракцию известных моделей данных. Требование PATCH для частичных обновлений, а не PUT для полного или частичного, похоже, что у него нет никакой пользы, но меня можно было убедить.

Похожие

http://restcookbook.com/HTTP%20Methods/idempotency/ - это означает, что у вас нет контроля над программным обеспечением сервера, которое может кэшировать запросы.

В чем причина отказа от частичного PUT? - нет четкого ответа, только ссылка на то, что HTTP определяет для PUt vs PATCH.

http://groups.yahoo.com/neo/groups/rest-discuss/conversations/topics/17415 - показывает разницу мыслей об этом.

4b9b3361

Ответ 1

Кто говорит? Парень, который изобрел REST, говорит:

@mnot Oy, да, PATCH было чем-то, что я создал для первоначального предложения HTTP/1.1, потому что частичный PUT никогда не был RESTful.; -)

https://twitter.com/fielding/status/275471320685367296

Прежде всего, REST является архитектурным стилем, и одним из его принципов является использование стандартизованного поведения протокола, лежащего в его основе, поэтому, если вы хотите внедрить RESTful API через HTTP, вы должны следовать HTTP строго для это будет RESTful. Вы можете не делать этого, если считаете, что это не подходит для ваших нужд, никто вас не проклинает, но тогда вы не делаете ОТДЫХ. Вам придется документировать, где и как вы отклоняетесь от стандарта, создавая сильную связь между реализацией клиента и сервера, и вся цель использования REST заключается в том, чтобы избежать этого и сосредоточиться на ваших типах носителей.

Итак, на основе RFC 7231 PUT следует использовать только для полной замены представления в операции идемпотента. PATCH следует использовать для частичных обновлений, которые не обязательно должны быть идемпотентными, но полезно сделать их идемпотентными, требуя предварительного условия или проверки текущего состояния перед применением diff. Если вам нужно делать не-идемпотентные обновления, частичные или нет, используйте POST. Просто. Каждый, кто использует ваш API, который знает, как работают PUT и PATCH, ожидает, что они будут работать таким образом, и вам не нужно документировать или объяснять, что методы должны делать для данного ресурса. Вы можете делать действия PUT любым другим способом, который вам подходит, но тогда вам придется документировать это для ваших клиентов, и вам придется найти еще одно модное слово для вашего API, потому что это не RESTful.

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

Ответ 2

Чтобы продлить на существующий ответ, PUT должен выполнить полное обновление (переписать) состояния ресурса просто потому, что HTTP определяет метод таким образом, оригинальный RFC 2616 о HTTP/1.1 не очень ясен, RFC 7231 добавляет смысловые пояснения:

4.3.4 PUT

Метод PUT запрашивает, чтобы состояние целевого ресурса было создано или заменено состоянием, определенным представлением, заключенным в полезной нагрузке сообщения запроса. Успешное PUT данного представления предполагает, что последующее GET на том же целевом ресурсе приведет к тому, что эквивалентное представление будет отправлено в ответ 200 (OK).

Как указано в другом ответе, соблюдение этого соглашения упрощает понимание и использование API-интерфейсов, и нет необходимости явно документировать поведение метода PUT.


Однако частичные обновления не запрещаются из-за идемпотентности. Я считаю это важным, чтобы выделить, так как эти понятия часто путают даже во многих ответах StackOverflow (например, здесь).

Idempotent исключительно означает, что применение запроса один или несколько раз приводит к тому же эффекту на сервере. Чтобы процитировать RFC 7231 еще раз:

4.2.2 Идемпотентные методы

Метод запроса считается "идемпотентным", если предполагаемый эффект на сервере с несколькими идентичными запросами с этим методом совпадает с эффектом для одного такого запроса.

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

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

Наоборот, операция, которая не является идемпотентной, зависит от текущего состояния сервера, поэтому она приводит к разным результатам в зависимости от того, сколько раз оно выполняется. Самый простой пример для этого - увеличение числа (не-идемпотент) против установки его к абсолютному значению (idempotent).

Для неидемпотентных изменений HTTP предусматривает методы POST и PATCH, тогда как PATCH явно предназначен для переноса изменений в существующий ресурс, тогда как POST можно более свободно интерпретировать относительно отношения запросить URI, содержимое тела и побочные эффекты на сервере.


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

Сам протокол HTTP ставит ограничения на то, что вы можете и чего не можете делать, и многие из них имеют практическое влияние. Например, игнорирование idempotency может привести к тому, что кэш-серверы изменят количество запросов, фактически выданных клиентом, и впоследствии нарушают логику, ожидаемую приложениями. Поэтому важно осознавать последствия, когда они отклоняются от стандарта.

Будучи строго REST-совместимым, нет полного удовлетворительного решения для частичных обновлений (некоторые даже говорят, что эта потребность одна против REST). Проблема в том, что PATCH, который, как представляется, делается именно для этой цели, не является идемпотентным. Таким образом, , используя PATCH для идемпотентных частичных обновлений, вы теряете преимущества idempotency(произвольное количество автоматических попыток, более простая логика, потенциал для оптимизации в клиенте, сервере и сети). Таким образом, вы можете спросить себя, является ли использование PUT действительно худшей идеей, пока поведение явно документировано и не прерывается, потому что пользователи (и промежуточные сетевые узлы) полагаются на определенное поведение...?

Ответ 3

Частичные обновления разрешены PUT (согласно RFC 7231 http://tools.ietf.org/html/rfc7231#section-4.3.4).

",... Запрос PUT определяется как замена состояния целевого ресурса." - замена части объекта в основном изменяет ее состояние.

"Обновления частичного контента возможны путем таргетинга отдельно идентифицированного ресурса с состоянием, которое перекрывает часть более крупного ресурса,..."

В соответствии с этим RFC следующий запрос действителен: PUT/resource/123 {name: 'new name'} Он изменит только имя для указанного ресурса. Указание полезной нагрузки id внутри запроса было бы неверным (поскольку PUT не разрешает частичные обновления для неуказанных ресурсов).

PS: Ниже приведен пример, когда PATCH полезен.

Внутри объекта есть массив. С помощью PUT вы не можете обновить определенное значение. Вы можете заменить весь список на новый. С помощью PATCH вы можете заменить одно значение на другое. С картами и более сложными объектами преимущество будет еще больше.