2011-06-13 43 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 /取消

哪是處理現有資源上的各種操作的通用方式。我不明白爲什麼取消訂單會導致訂單本身的刪除,至少不會立即刪除。用戶可能仍然希望看到系統中的訂單。訂單也是您存放取消原因的地方。