web services проектирование Что делать, когда вам нужно больше глаголов в REST



rest api пример (3)

Что делать, когда вам нужно больше глаголов в REST

У вас есть 3 варианта:

  • создать новый ресурс и использовать доступные HTTP-методы для описания того, что вы хотите
  • проверьте стандарт, возможно, вам не хватает уже существующего метода
  • отправьте новый RFC о желаемом методе ietf, возможно, они его принимают

В вашем случае вы просто пропустили RFC метода PATCH через месяц или два.

https://src-bin.com

У меня есть другой аналогичный question , но обсуждение отошло от проблемы, с которой я сталкиваюсь.

Скажем, у меня есть система, которая занимается отчетами о расходах (ER). Вы можете создавать и редактировать их, добавлять вложения и одобрять / отклонять их.

Отчет о расходах может выглядеть следующим образом:

GET /er/1
=>
{"title": "Trip to NY", "totalcost": "400 USD",
 "comments": [
   "john: Please add the total cost",
   "mike: done, can you approve it now?"
   ],
 "approvals": [
   {"john": "Pending"}, {"finance-group": "Pending"}]
}

Это выглядит хорошо, не так ли? Вот как выглядит документ отчета о расходах.

Если вы хотите его обновить, вы можете сделать это:

POST /er/1
{"title": "Trip to NY 2010"}

Если вы хотите его одобрить, вы можете сделать это:

POST /er/1/approval
{"approved": true}

Но что, если вы хотите обновить отчет и одобрить его одновременно? Как мы это делаем? Если вы только хотели одобрить, то сделать POST на что-то вроде /er/1/approval имеет смысл.

Мы могли бы поместить флаг в URL-адрес, POST /er/1?approve=1 и отправить данные в виде тела, но этот флаг не выглядит RESTful.

Мы могли бы также поставить специальное поле, но это тоже немного взломано. Если бы мы это сделали, то почему бы не отправить данные с такими атрибутами, как set_title или add_to_cost ?

Мы могли бы создать новый ресурс для обновления и утверждения, но (1) я не могу думать о том, как назвать его без глаголов, и (2) не представляется правильным назвать ресурс, основанный на том, какие действия можно сделать для это (что произойдет, если мы добавим больше действий?)

У нас может быть заголовок X-Approve: True | False, но заголовки кажутся неправильным инструментом для работы. Также было бы сложно получить заголовки, не используя javascript в браузере.

Мы могли бы использовать пользовательский медиа-тип, application/approve+yes , но это не лучше, чем создание нового ресурса.

Мы могли бы создать временный URL-адрес «пакетных операций», /er/1/batch/A Затем клиент отправляет несколько запросов, возможно, POST /er/1/batch/A для обновления, затем одобряет POST /er/1/batch/A/status , а затем POST /er/1/batch/A/status чтобы завершить партия. На бэкэнд сервер останавливает все пакетные запросы где-то, а затем обрабатывает их в одной и той же бэкэнд-транзакции, когда получает запрос «окончательная пакетная обработка». Недостатком этого является, очевидно, то, что он вводит большую сложность.

Итак, какой хороший, общий способ решить проблему выполнения нескольких действий в одном запросе? Потому что его легко представить дополнительные действия, которые могут быть выполнены по одному и тому же запросу:

  1. Подавлять или отправлять уведомления (на электронную почту, чат, другую систему, что угодно)
  2. Переопределите некоторую проверку (максимальная стоимость, имена участников обеда)
  3. Триггерный рабочий процесс, который не имеет представления в документе.

Это также проблема производительности. HTTP-вызовы попадают в сеть (что может быть проблемой, если у вас высокая латентность или слабое соединение), поэтому чем меньше их вы можете сделать, тем лучше.


Answer #1

Архитектура REST говорит, что ресурс управляется сервером и идентифицируется URL-адресом.

В этом свете /er/1/approval не является разумным URL-адресом или моделью, если у вас нет объекта или объекта утверждения, которым вы управляете и управляете на стороне сервера. Кажется, что сущность - это сам отчет о расходах, что означает, что /er/1 - ваш URL-адрес.

Теперь, что касается глаголов ... вы можете отправить (POST) любое сообщение, которое вам нравится на этом ресурсе.

установить данные:

{ action: "modify", data: { purpose : "Club hopping" } }

одобрить:

{ action: "approve" }

добавить элемент:

{ action:"additem", data: { amount:72.13, category:113, note:"client dinner" }}

и т.п.

Из Ching Fielding, который определил REST ,

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

...а также...

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

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

{ action: "modify", data: { purpose : "Club hopping" } }
{ action: "approve" }

Но вы, вероятно, захотите обобщить это так, чтобы это было:

{ actions: [ {action:"modify", data: {...} }, { action:"approve"} ] } 

Сообщения и действия, которые ваш сервер может обрабатывать для каждого конкретного типа объекта, могут определить вас.

ps: иногда реализации REST используют HTTP PUT для создания ресурса и POST для изменения или использования существующего ресурса.

и: Мне понравилась статья « Как получить чашку кофе» .


Answer #2

Я думаю, вы делаете это более сложным, чем это должно быть. Относитесь к своему отчету о расходах как к полному ресурсу, и любые изменения для него - это просто вопрос о представлении нового представления в URI, где живет ресурс. Нет необходимости иметь настраиваемые действия для изменения статуса, просто ПОЛУЧИТЕ ресурс - сделайте свои изменения - затем ОТКЛЮЧИТЕ его. Готово.





rest