Как спроектировать REST API для обработки операций без CRUD?

11

Я пытаюсь преобразовать набор сервисов на основе SOAP в API RESTful.

Я начал с определения ресурсов путем анализа имен операций и получил ресурс Subscription.

Когда мне нужно обновить состояние подписки, я не могу просто отправить POSTзапрос на сервер, потому что у меня нет прямого доступа к ресурсам, но мне нужно вызвать некоторые операции в стиле RPC для обновления их свойств. Кроме того, только и только если я изменяю состояние подписки на «активный», требуется дополнительный вызов внешней службы.

В этих случаях, какова лучшая практика для обработки базовых операций?

Решение, которое я придумал, состоит в том, чтобы использовать параметры запроса, так что если мне нужно вызвать службу активации, я могу использовать что-то вроде:

POST /subscriptions/{subscriptionid}/?activate=true

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

Обновление 1:

Я могу поместить в тело моего запроса POST некоторые значения, например, «state»: «active»

и проверьте в моем сервисе правильные операции, которые будут запущены.

Vektor88
источник
REST-сопоставление команд с HTTP-глаголами не удается при сложных операциях. Вам лучше всего сделать вызов в стиле RPC POST activSubscription / {id} это никого не смущает
Ewan
@Ewan Я не уверен, что это соответствует модели RESTful, но я нашел другое решение: в своем коде я могу вызвать правильную операцию в стиле RPC в соответствии с входной полезной нагрузкой (я могу передать state = active в теле мой пост запрос, код назову кодом активации)
Vektor88
1
Такое обновление существующего ресурса, как это, должно быть PATCH, а тело запроса - это частичная модель того, что вы меняете. Предполагается, что POST - это запрос, который создает ресурс. Это различие, помимо того, что оно более понятно пользователю, облегчит вашему коду знать, когда происходит эта операция, а не публикация ресурса.
Мистер Кочезе
1
@ Vektor88 Как правило, но это идемпотентные операции, в которых необходимо передать полное представление состояния ресурса. Этот вариант использования выглядит скорее как частичное обновление, которое действительно хорошо подходит для PATCH.
Мистер Кочезе
1
@MrCochese POST не идемпотентен.
JimmyJames

Ответы:

8

Вам нужно посмотреть этот разговор Джима Уэббера.

Когда мне нужно обновить состояние подписки, я не могу просто отправить запрос POST на сервер, потому что у меня нет прямого доступа к ресурсам, но мне нужно вызвать некоторые операции в стиле RPC для обновления их свойств. Кроме того, только и только если я изменяю состояние подписки на «активная», требуется дополнительный вызов внешней службе.

Подумайте «обмен сообщениями»; отправьте сообщение на свой домен, описав, что вы хотите, чтобы произошло. Побочным эффектом сообщения является то, что модель вашего домена фактически меняет свое состояние. «Ресурс» - это очередь сообщений.

POST /subscriptions/{subscriptionid}/?activate=true

Написание имени ресурса не имеет значения для машин; но люди склонны суетиться, когда используемые вами идентификаторы выходят за рамки соглашения о том, что ресурсы являются "существительными".

Кроме того, мы говорим о ресурсе, который подчиняется /subscriptions/{subscriptionid}, поэтому соглашение (см. RFC 3986 ) требует выражения этой связи с сегментом пути, а не с использованием части запроса.

Таким образом, эти написания могут быть разумными

POST /subscriptions/{subscriptionid}/messages
POST /subscriptions/{subscriptionid}/activations
VoiceOfUnreason
источник
1
Доклад
0

Если это логический флаг для активации / деактивации, я бы сказал, что по умолчанию используется JSON:

POST /subscriptions/{subscriptionid}/
{
    format: 0,
    subscription: 
    {
        active: false
    }
}

Это легко расширить, если вы хотите поддерживать больше свойств. Другой подход - дать ему собственную конечную точку:

POST /subscriptions/{subscriptionid}/active/
DELETE /subscriptions/{subscriptionid}/active/

Лично я бы использовал это, только если activeсостояние этого события нуждается / имеет свойства, которые вы затем можете передать / получить в JSON, такие как идентификатор пользователя или параметр.

Если это не логическое значение, а просто действие, которое вам нужно вызвать, но не нужно / не иметь какой-либо обратной связи о состоянии (кроме немедленного 200 OK), я бы использовал конечную точку, подобную этой, чтобы вызвать ее, как RPC:

POST /subscriptions/{subscriptionid}/activate/

Если вы сомневаетесь, прочитайте это: http://www.vinaysahni.com/best-practices-for-a-pragmatic-restful-api#restful (см. «Как насчет действий, которые не вписываются в мир операций CRUD?»). «)

Барри Стес
источник
0

ОТДЫХ не работает. Activateэто глагол и не может быть состоянием, Activeэто состояние.

Поскольку RESTful не работает, вы не можете указать службе RESTful, что делать, но вы можете добавить работу для очереди службы.

Посмотри это:

PUT /subscriptionQueue
subscriptionId={subscriptionId}
active=true

Этот запрос является RESTful и поддерживает все преимущества RESTful (такие как производительность, кислота ...)

Питер Рейдер
источник