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.