我对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,但这个问题正在勉强看着我。
答案 0 :(得分:6)
一个选项可能是创建新资源。或许CancelledOrder
。
然后,您可以POST
新的CancelledOrder
:
POST /ecommerce/cancelledOrder
Entity:
order: /ecommerce/order/123
reason: "Problem with order"
您还可以/而PUT
CancelledOrder
:
PUT /ecommerce/cancelledOrder/123
Entity:
reason "Problem with order"
然后,应用程序可以删除订单123或将其状态更新为“已取消”,或执行您的业务规则要求的任何操作。最重要的是,您可能不会直接为DELETE
支持/ecommerce/order/N
方法,并返回405 Method Not Allowed
。
PUT
解决方案可以使用幂等优势; <{1}}多次PUT
总是会导致订单被取消。
应该注意的是,您更改API的建议(例如CancelledOrder
)可能不是RESTful,因为您在资源标识符中定义了方法。
答案 1 :(得分:4)
我知道这是一个非常晚的答案,但我建议使用第一组命令,但将cancel order命令更改为:
POST /电子商务/订单/ 123 /取消
这是处理现有资源上的各种操作的通用方法。我不明白为什么订单取消会导致订单本身被删除,至少不会立即删除。用户可能仍希望查看系统中的订单。订单也是您存储取消原因的地方。
答案 2 :(得分:2)
(这个问题很老了,但我只是觉得我会改进它,因为我不喜欢任何解决方案。)
解决方案很简单。将一个理由放入请求的主体。
DELETE /ecommerce/order/123
Content-Type: text/plain
Content-Length: 48
Order was cancelled due to a customer's request.
身体的语义由你来决定。如果您只想要明文原因,我可以使用text / plain,如上所示。如果需要更复杂的元数据,我会进一步复杂化。
在我看来,这比Javaesque类似OrderCancellator.execute(order)
更好(因为POST是&#34的名称;执行&#34;)。
请注意,虽然规范并没有说出相关信息,但有些服务器may discard DELETE request's body。 draft on HTTP/1.1 message semantics澄清:
DELETE请求上的实体没有定义的语义。注意 在DELETE请求上发送正文可能会导致一些存在 拒绝请求的实现。
另一种选择是发出标题:
DELETE /ecommerce/order/123
X-Reason: Cancelled due to an UFO invasion.
每当选择标题或实体主体时,取决于数据的大小和格式。有些数据适合HTTP标头,有些则不适合。一个肯定可以通过数字票证ID,它不确定字符串(想想Unicode),并且他们的理智中没有人想要在那里传递Base64 JPEG。