API REST с несколькими командами на ресурс

У меня есть вопрос относительно дизайна REST API. Вот простой (может быть, простой) API:

GET /ecommerce/order/123

POST /ecommerce/order (create a new order)

PUT /ecommerce/order/123 (update an existing order)

DELETE /ecommerce/order/123 (cancel order)

Но что, если я хочу, чтобы клиент ввел причину отмены заказа? Мне нужно будет отправить данные сообщения в API, но это не будет работать с DELETE. Чтобы справиться с этим, мне пришлось бы изменить DELETE на PUT. Затем я разместил два разных ресурса для обновления и отмены.

Другим решением было бы изменить API:

GET /ecommerce/order/123

POST /ecommerce/order/create (create a new order)

PUT /ecommerce/order/update/123 (update an existing order)

DELETE /ecommerce/order/cancel/123 (cancel order)

Я не уверен, что лучший вариант.

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

Любой ввод будет оценен! Я очень скоро буду читать REST на практике, но этот вопрос на меня отвлекает.

Ответ 1

Одним из вариантов может быть создание нового ресурса. CancelledOrder, возможно.

Тогда вы можете POST создать новый CancelledOrder:

POST /ecommerce/cancelledOrder
Entity:
    order: /ecommerce/order/123
    reason: "Problem with order"

Вы также можете/вместо PUT a CancelledOrder:

PUT /ecommerce/cancelledOrder/123
Entity:
    reason "Problem with order"

Приложение может затем удалить заказ 123 или обновить свой статус до "Отменено" или выполнить все, что требуется для ваших бизнес-правил. В довершение всего, вы могли бы не поддерживать метод DELETE непосредственно для /ecommerce/order/N, возвращая 405 Method Not Allowed.

Решение PUT может использовать идемпотенцию в своих интересах; PUT ting CancelledOrder несколько раз всегда будет приводить к отмене заказа.

Следует отметить, что ваши предложения по изменению API (например, /ecommerce/order/create) скорее всего не будут RESTful, поскольку вы определяете методы в идентификаторах ресурсов.

Ответ 2

Я знаю, что это очень поздний ответ, но я предлагаю использовать первый набор команд, но изменить команду отмены порядка:

POST/электронная торговля/заказ/123/отменить

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

Ответ 3

(Вопрос довольно старый, но я просто подумал, что улучшу его, так как мне не нравятся какие-либо решения там.)

Решение прост. Поместите причину в тело запроса.

DELETE /ecommerce/order/123
Content-Type: text/plain
Content-Length: 48

Order was cancelled due to a customer request.

Семантика тела зависит от вас, чтобы решить. Если вам нужна только причина открытого текста, я бы использовал текст /plain, как показано выше. Если требуются более сложные метаданные, я бы усложнил ситуацию.

По-моему, это намного лучше, чем Javaesque RPC-like OrderCancellator.execute(order) (потому что POST - это HTTP-имя для "execute" ).

Остерегайтесь, что, хотя спецификация не говорит об этом, некоторые из них могут отменить тело запроса DELETE. A черновик в HTTP/1.1 семантике сообщений уточняет:

Тела в запросах DELETE не имеют определенной семантики. Обратите внимание, что отправка тела по запросу DELETE может привести к чтобы отклонить запрос.

Другой вариант - создать заголовок:

DELETE /ecommerce/order/123
X-Reason: Cancelled due to an UFO invasion.

Всякий раз, когда выбирать заголовки или сущность тела зависит от размера и формата данных. Некоторые данные отлично подходят для HTTP-заголовков, а некоторые нет. Конечно, можно передать числовой идентификатор билета, он не уверен в строках (думаю, Unicode), и он определенно никому в своем здравом уме не хочет пропускать там Base64 JPEG.