REST - изменение части ресурса - PUT или POST

Я вижу хороший размахивающий рукой вопрос о том, как обновлять только часть ресурса (например, индикатор состояния) с помощью REST.

Возможные варианты:

  • Пожаловаться на то, что у HTTP нет команды PATCH или MODIFY. Тем не менее, принятый ответ HTTP MODIFY verb для REST? показывает, почему эта идея не так хороша, как может показаться.

  • Используйте POST с параметрами и определите метод (например, параметр с именем "действие" ). Некоторые рекомендации заключаются в том, чтобы указать заголовок X-HTTP-Method-Override с самоопределяемым именем метода. Это, по-видимому, приводит к уродливости перехода в рамках реализации, основанной на том, что вы пытаетесь сделать, и быть открытым для критики того, что не являетесь особенно RESTful способом использования POST. Фактически, этот подход начинает ощущаться как интерфейс типа RPC.

  • Используйте PUT для перезаписи суб-ресурса ресурса, который представляет определенные атрибуты для обновления. Фактически, это эффективно переписывание подресурса, что похоже на дух PUT.

В этот момент я вижу # 3 как наиболее разумный вариант.

Является ли это лучшей практикой или анти-шаблоном? Существуют ли другие варианты?

Ответ 1

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

Придерживайтесь 3-х и используйте более гранулированные под-ресурсы, и если у вас действительно есть потребность в PATCH-подобном поведении - используйте POST. Лично я по-прежнему буду использовать этот подход, даже если PATCH действительно окажется в качестве жизнеспособного варианта.

Ответ 2

Существует два способа просмотра обновления состояния.

  • Обновить вещь. Это ПУТЬ. Вариант 3

  • Добавление дополнительной записи журнала в историю вещи. Элементом списка в этой последовательности записей журнала является текущий статус. Это ПОСТ. Вариант 2.

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

В противном случае вы не против "обновления", чтобы изменить статус вещи, и вы довольны PUT. Это не отличает вещь и ее историю, а хранит все в одной таблице.

Лично я считаю, что я все меньше доверяю изменяемым объектам и PUT (кроме "исправления ошибок" ). (И даже тогда я думаю, что старая вещь может быть оставлена ​​на месте, а новая вещь добавлена ​​со ссылкой на предыдущую версию.)

Если есть изменение статуса, я думаю, что должен быть журнал состояния или история, и для добавления новой записи в эту историю должен быть POST. Может быть какая-то оптимизация, чтобы отразить "текущий" статус в объекте, к которому это применимо, но это просто за кадром оптимизации.

Ответ 4

Это нормально для POST & emulating PATCH, где не доступно


Прежде чем объяснять это, вероятно, стоит упомянуть, что нет ничего плохого в том, что с помощью POST делать общие обновления (см. здесь) В частности:

POST становится проблемой, когда он используется в ситуации, для которой идеально подходит какой-либо другой метод: например, поиск информации, которая должна быть представлением некоторого ресурса (GET), полная замена представления (PUT)

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

Наш сервис должен быть открыт для сторонних продуктов, таких как SAP, Flex, Silverlight, Excel и т.д. Это означает, что мы должны использовать самую низкую общую технологию знаменателей - некоторое время мы не могли использовать PUT, потому что только GET и POST поддерживались всеми клиентскими технологиями.

Подход, с которым я столкнулся, состоит в том, чтобы иметь "_method = patch" как часть запроса POST. Преимущества:

(a) Он легко справляется с на стороне сервера - мы в основном притворяемся, что PATCH доступен

(b) Он указывает третьим сторонам, что мы не нарушаем REST, но работаем с ограничением с браузером. Это также согласуется с тем, как PUT обрабатывался несколькими годами назад сообществом Rails, поэтому должно быть понятным многими

(c) легко заменить, когда PATCH становится более доступным

(d) Это a прагматичный ответ на неудобную проблему.

Ответ 5

PATCH отлично подходит для патчей или форматов. До тех пор это не очень полезно вообще.

Что касается вашего решения 2 с помощью настраиваемого метода, будь то в запросе или в заголовках, нет нет нет нет и нет, это ужасно:)

Допустимы только два способа: либо PUT весь ресурс, либо модифицированные вспомогательные данные, либо POST для этого ресурса, либо PUT для под-ресурса.

Все зависит от детализации ваших ресурсов и предполагаемых последствий для кеширования.

Ответ 6

Немного опоздал с ответом, но я бы подумал об использовании JSON Patch для подобных сценариев.

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

Пример этого:

[
  { "op": "replace", "path": "/baz", "value": "boo" },
  { "op": "add", "path": "/hello", "value": ["world"] },
  { "op": "remove", "path": "/foo" }
]

Есть много клиентских библиотек, которые могут сделать тяжелую работу в