REST - изменить часть ресурса - PUT или POST - PullRequest
15 голосов
/ 05 февраля 2010

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

Возможны следующие варианты:

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

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

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

На данный момент, я считаю № 3 наиболее разумным вариантом.

Это лучшая практика или анти-паттерн? Есть ли другие варианты?

Ответы [ 6 ]

7 голосов
/ 05 февраля 2010

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

  1. Обновление до вещи. Это ПОЛ. Вариант 3

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

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

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

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

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

5 голосов
/ 05 февраля 2010

HTTP имеет команду PATCH. Он определен в Разделе 19.6.1.1 RFC 2068 и обновлен в draft-dusseault-http-patch-16 , в настоящее время ожидающей публикации как RFC .

5 голосов
/ 05 февраля 2010

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

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

1 голос
/ 08 февраля 2010

PATCH подходит для patch или diff форматов. До тех пор, пока это не очень полезно.

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

Только два допустимых способа - это PUT для всего ресурса с измененными субданными, или POST для этого ресурса, или PUT для субресурса.

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

1 голос
/ 05 февраля 2010

Это нормально для POST и эмуляции PATCH, где нет в наличии
Прежде чем объяснить это, вероятно, стоит упомянуть, что нет ничего плохого в использовании POST для общих обновлений (см. здесь ) В частности: POST становится проблемой только тогда, когда он используется в ситуации, для которой идеально подходит какой-то другой метод: например, поиск информации, которая должна быть представлением некоторого ресурса (GET), полная замена представления ( PUT) На самом деле мы должны использовать PATCH для небольших обновлений сложных ресурсов, но он не так широко доступен, как хотелось бы. Мы можем эмулировать PATCH, используя дополнительный атрибут как часть POST. Наш сервис должен быть открыт для сторонних продуктов, таких как SAP, Flex, Silverlight, Excel и т. Д. Это означает, что мы должны использовать технологию наименьшего общего знаменателя - какое-то время мы не могли использовать PUT, потому что во всех клиентских технологиях поддерживаются только GET и POST. Подход, который я использовал, заключается в том, чтобы использовать _method = patch как часть запроса POST. Преимущества: (a) С легко справиться с *1019* на стороне сервера - мы в основном притворяемся, что PATCH доступен (b) Это указывает третьим сторонам, что мы не нарушаем REST , а работаем над ограничением с помощью браузера. Это также согласуется с тем, как PUT был обработан сообществом Rails несколько лет назад, поэтому должно быть понятно многим (c) легко заменить , когда PATCH становится более доступным (d) Это прагматичный ответ на неловкую проблему.

0 голосов
/ 29 января 2019

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

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

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

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

Существует множество клиентских библиотек , которые могут выполнить всю работу по генерации

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...