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

Разоблачение операций с ресурсами RESTfully - перегруженные ресурсы POST vs. PUT и контроллеров

Скажем, у вас есть ресурс Person, а часть его представления включает значение местоположения, которое может иметь такие значения, как "дома", "в школе" и "на работе". Как бы вы RESTfully выставлять такие действия, как "идти домой", "идти на работу", "ходить в школу" и т.д.? В целях обсуждения давайте укажем, что эти действия требуют времени, поэтому они выполняются асинхронно, и существуют различные способы, с помощью которых они могут потерпеть неудачу (нет доступных транспортных средств, транспортная разлома во время путешествия, другой акт Бога и т.д.), Кроме того, ресурс Person имеет другие атрибуты и связанные с ними операции, которые влияют на эти атрибуты (например, атрибут = уровень энергии, операции = есть/сон/упражнение).

Вариант 1. Перегрузка POST на ресурсе Person, предоставляющая входной параметр, указывающий, что вы хотите сделать человеку (например, action = go-to-school). Верните 202 из POST и опубликуйте атрибуты статуса незавершенного процесса в представлении Person, которое клиент может ПОЛУЧИТЬ, чтобы наблюдать прогресс и успех/неудачу.

Преимущества: он прост.

Недостатки: сводится к туннелированию. Выполнение действия засыпается в полезной нагрузке вместо того, чтобы быть видимым в URI, глаголе, заголовках и т.д. Глагол POST на этом ресурсе не имеет единого семантического значения.

Вариант 2. Используйте PUT, чтобы установить местоположение Person в состояние, которое вы хотели бы иметь. Верните 202 из PUT и выверите атрибуты активности в процессе для опроса статуса через GET.

Преимущества: Не уверен, что я вижу.

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

Вариант 3: выставить общий ресурс контроллера, который работает с объектами Person. Например, создайте ресурс PersonActivityManager, который принимает запросы POST с аргументами, которые идентифицируют целевое Лицо и запрошенное действие. POST может вернуть ресурс PersonActivity для представления текущей активности, которую клиент мог бы получить, чтобы отслеживать прогресс и успех/сбой.

Преимущества: Кажется немного более чистым, отделяя активность и ее статус от ресурса Person.

Недостатки: теперь мы переместили туннелирование на ресурс PersonActivityManager.

Вариант 4: Установите отдельные ресурсы контроллера для каждого поддерживаемого действия, например. ресурс ToWorkTransporter, который принимает запросы POST с аргументом (или элементом URI), который идентифицирует Person, плюс ToHomeTransporter, ToSchoolTransporter, MealServer, Sleeper и Exerciser. Каждый из них возвращает соответствующий ресурс мониторинга задач (Commute, Meal, Slumber, Workout) из своего метода POST, который клиент может контролировать через GET.

Преимущества: Хорошо, мы, наконец, исключили туннелирование. Каждый POST означает только одно.

Недостатки: теперь речь шла о большом количестве ресурсов (возможно, мы могли бы объединить транспортеры в один Transporter, который принимает аргумент назначения). И некоторые из них довольно семантически надуманны (Спящий?). Это может быть больше RESTful, но насколько это практично?

4b9b3361

Ответ 1

Хорошо, я изучал и размышлял об этом примерно неделю. Поскольку никто не ответил, я опубликую результаты того, что я узнал.

Тим Брей, в RESTful Casuistry, рассказывает о запуске поля состояния и POST-IN для контроллера, который будет выполнять операцию, влияющую на это состояние. Он использует пример виртуальной машины и как RESTfully выставлять функцию "кнопки перезагрузки". Он говорит

"Если я хочу обновить некоторые поля в существующем ресурсе, Im наклонен думать о PUT. Но это не работает, потому что это должно быть idempotent и перезагрузка сервера обязательно. Хорошо, хорошо, сделай это с ПОСТ, я думаю; нет biggie.

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

Итак, чем больше я думаю об этом, тем больше я думаю, что эти ресурсы как кнопки, только с одной определенной операцией: push. Люди были скулить о" ресурсах только для записи ", но у меня нет проблем с потому что это кажется точным. Кнопки перезагрузки и остановки dont действительно имеют какое-либо состояние, поэтому вы не должны ожидать ничего полезного от GET".

Тим, похоже, где-то находится между моим вариантом №3 и №4, выставляя несколько ресурсов контроллера, но отступая от "перебора" и имея отдельные ресурсы контроллера для всего.

Сообщение Тима привело к другому Рою Филдингу (Хорошо использовать POST), в котором он говорит, что для ситуаций, где есть контролируемое состояние сущности, и чтобы потенциально изменить это состояние, он склонен использовать POST, а не PUT. В ответ на предложение комментатора о том, чтобы обнародовать контролируемое состояние как отдельный ресурс, пригодный для PUT, он говорит

"мы используем только PUT, когда действие обновления является идемпотентным, и представление завершено. Я думаю, мы должны определить дополнительную когда мы думаем, что ресурс может быть полезен другим изоляции и использовать методы GET/PUT для этого ресурса, но Я не думаю, что мы должны определить новые ресурсы только ради избегая POST."

Наконец, Bill de hOra, в Просто используйте POST, обсуждает конкретный случай использования PUT vs. POST для обновления состояния ресурса коллекции и компромиссов в нем.