2011-06-13 79 views
10

多个命令REST API我有一个关于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,但是这个问题对我来说很小。

回答

6

一个选择是创建一个新的资源。可能是CancelledOrder

你可能再POSTCancelledOrder

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溶液可以使用幂等它的优势; PUT多次都会导致订单被取消。

需要注意的是,由于您在资源标识符中定义了方法,因此您对更改API的建议(例如/ecommerce/order/create)可能不是RESTful。

+0

我喜欢这答案。资源和域名实体不是一一对应的。 – 2011-06-13 21:09:30

+1

我不太喜欢CancelledOrder的名字,更好的资源名称是OrderCancellation,或者换句话说,将操作公开为资源。这在可逆操作的情况下也很好,因为您可以在“操作”上使用删除。 – Maxem 2011-06-15 16:11:37

+0

此外,当这不太合适,我喜欢这个评论提到了同样的问题:http://programmers.stackexchange.com/a/270421/211215 – Almund 2016-01-15 09:07:48

2

(现在的问题是很老,但我只是想我会改善它,因为我不喜欢任何解决方案在那里。)

解决方法很简单。在请求的正文中加入一个理由。

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

Order was cancelled due to a customer's request. 

身体的语义是由你来决定。如果你只想要一个纯文本的原因,我会使用上面显示的text/plain。如果需要更复杂的元数据,我会进一步复杂化。

在我看来,这比Javaesque RPC-like OrderCancellator.execute(order)(因为POST是HTTP的“execute”名称)更好。

请注意,尽管spec没有提到它,但有些服务器may discard DELETE request's body。A 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那里。

+0

对我而言,取消原因似乎是属于某种资源。标题(根据我的理解)应该是关于请求本身的元信息,而不是实际的业务数据。 “删除”主体/实体建议有潜力,但您提供的链接确实引起了一些担忧。 – 2012-05-02 16:01:43

+0

AFAIK没有什么说DELETE不能有副作用,所以你不必使用不明确的POST语义显示创建取消资源(这会删除订单以及创建取消记录)。 以同样的方式,GET被认为是幂等的,但是将记录写入访问日志文件或[增加计数器](http://www.intertwingly.net/blog/784.html)并不违反它。 尽管如此,使用标记为已取消的更新版本来下订单(取代)似乎很好。 – drdaeman 2012-05-02 20:47:16

+0

真实点。我其实今天又看了一遍我的回答,发现自己对此有所保留。它仍然有效,但有更好,更超文本驱动的方式来实现这一点。我正在研究另一个答案,但分心。 – 2012-05-02 20:51:27

4

我知道这是一个非常晚的答案,但我建议使用第一组命令,而是修改取消订单命令:

POST /电子商务/顺序/ 123 /取消

哪是处理现有资源上的各种操作的通用方式。我不明白为什么取消订单会导致订单本身的删除,至少不会立即删除。用户可能仍然希望看到系统中的订单。订单也是您存放取消原因的地方。