Как поддерживать частичные обновления (PATCH) в REST

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

HTTP MODIFY глагол для REST?

Как отправить частичные обновления RESTful?

http://jacobian.org/writing/rest-worst-practices/

https://github.com/archiloque/rest-client/issues/79

http://tools.ietf.org/html/draft-dusseault-http-patch-16

http://greenbytes.de/tech/webdav/draft-dusseault-http-patch-06.html

http://jasonsirota.com/rest-partial-updates-use-post-put-or-patch

http://bitworking.org/news/296/How-To-Do-RESTful-Partial-Updates

https://github.com/dharmafly/jsonpatch.js

Пожалуйста, предложите любое допустимое решение для этого.

Ответ 1

PATCH следует использовать с форматом патча, только для патчей на уровне документа (также как и для фактического представления). Его использование для других целей является сомнительным и спорным, и неясно, что этот метод был разработан для использования в не-медиа-типе.

В общем, POST будет правильным, но вы можете разделить свой ресурс на несколько ресурсов и вместо этого изменить их.

[Отредактировано для ясности, поскольку некоторые не читают комментарии]

Ответ 2

Согласно RFC5789 (http://tools.ietf.org/html/rfc5789), это именно то, для чего PATCH предназначен для:

Несколько приложений, расширяющих протокол передачи гипертекста (HTTP)    требуется функция для частичной модификации ресурсов. Существующий    Метод HTTP PUT позволяет полностью заменить документ.    Это предложение добавляет новый HTTP-метод PATCH для изменения существующего    HTTP-ресурс.

Различие между PATCH и PUT описывается как:

Разница между запросами PUT и PATCH отражается в    как сервер обрабатывает закрытый объект для изменения ресурса    идентифицированных Request-URI. В запросе PUT закрытый объект    считается модифицированной версией ресурса, хранящегося на    исходного сервера, и клиент запрашивает, чтобы сохраненная версия    быть заменен. Однако с помощью PATCH закрытый объект содержит набор    инструкций, описывающих, как ресурс, находящийся в настоящее время на    исходный сервер должен быть изменен для создания новой версии.

Также описаны ограничения POST:

Метод PUT уже определен для перезаписывания ресурса    с полным новым телом и не может быть повторно использован для частичных изменений.    В противном случае прокси-серверы и кэши, а также клиенты и серверы могут получить    путают в отношении результата операции. POST уже используется, но    без широкой функциональной совместимости (например, нет стандартного способа    найти поддержку формата патча) [...]

Я бы посоветовал вам прочитать RFC и составить свое мнение, но для меня это кажется довольно четким - запросы PATCH должны обрабатываться как частичные обновления. (NB они не являются идемпотентными, в отличие от PUT.)

EDIT: как отметил Юджин в комментариях, хотя запросы PATCH "neither safe nor idempotent as defined by [RFC2616]", их можно сделать так:

Запрос PATCH может быть выдан таким образом, чтобы быть идемпотентным,    что также помогает предотвратить плохие результаты от столкновений между двумя    PATCH запрашивает один и тот же ресурс за аналогичный период времени.    Коллизии от нескольких запросов PATCH могут быть более опасными, чем    PUT, поскольку некоторые форматы патчей должны работать от    известную базовую точку, иначе они испортят ресурс. клиенты    использование такого типа патч-приложений СЛЕДУЕТ использовать условный запрос    так что запрос будет терпеть неудачу, если ресурс был обновлен    поскольку клиент последний раз обратился к ресурсу. Например, фотограф    может использовать сильный ETag [RFC2616] в заголовке If-Match на PATCH    запрос.

Ответ 3

Вы должны использовать метод PATCH, как описано в RFC-7386 "json merge PATCH".

например. если вы хотите изменить значение "a" и удалить "f" в ресурсе, например:

   {
     "a": "b",
     "c": {
       "d": "e",
       "f": "g"
     }
   }

Вы можете добиться этого, отправив:

       PATCH /target HTTP/1.1
       Host: example.org
       Content-Type: application/merge-patch+json

       {
         "a":"z",
         "c": {
           "f": null
         }
       }