2009-09-15 67 views
19

我有一個擁有計數器的資源。例如起見,我們不妨將資源輪廓,而計數器的意見該配置文件的數量。以RESTful方式遞增資源計數器:PUT vs POST

根據REST wiki,PUT請求應該用於資源創建或修改,並且應該是冪等的。如果我正在更新配置文件的名稱,那麼這種組合很好,因爲我可以發出一個PUT請求,它將名稱設置爲1000次,結果不會改變。

對於這些標準的PUT請求,我的瀏覽器做類似:

PUT /profiles/123?property=value&property2=value2 

對於遞增計數器,一個調用的URL像這樣:

PUT /profiles/123/?counter=views 

每次調用將導致計數器被遞增。從技術上講,這是一個更新操作,但它違反了冪等性。

我在尋找指導/最佳實踐。你只是做這個POST嗎?

回答

8

另一種方法可能是向系統添加另一個資源以跟蹤配置文件的查看。你可以稱之爲「查看」。

要查看配置文件的所有收看:

GET /型材/ 123 /收看

一個觀景添加到配置文件:

POST /型材/ 123 /收看#here,你'd在請求正文中使用自定義媒體類型提交詳細信息。

要更新現有查看:

PUT /使用創建的自定義媒體類型的請求體觀看的收看/ 815#提交修改後的屬性。

下鑽到觀看的細節:

GET /收看/ 815

要刪除查看:

DELETE /收看/ 815

而且,因爲你」要求最佳實踐,請確保您的RESTful系統是hypertext-driven

大多數情況下,在URI中使用查詢參數沒有任何問題 - 只是不要讓客戶想到他們可以操縱它們。

相反,創建一個媒體類型,體現參數試圖建模的概念。給這個媒體類型一個簡潔,明確,描述性的名字。然後記錄這種媒體類型。在REST中公開查詢參數的實際問題是,這種做法通常會導致帶外通信,因此會增加客戶端與服務器之間的耦合。

然後給你的系統一個統一的界面。例如,添加新資源始終是POST。更新資源總是PUT。刪除是DELETE,getiing是GET。

關於REST最難的部分是理解媒體類型是如何影響系統設計的(這也是Fielding因爲時間耗盡而離開論文的部分)。如果您想要使用和打印媒體類型的超文本驅動系統的特定示例,請參閱Sun Cloud API

+0

只是爲了澄清:/觀看/ 815是指第815個配置文件的查看,是嗎? – 2010-06-13 09:50:54

9

我認爲正確的答案是使用PATCH。我沒有看到任何人推薦它應該用於原子遞增計數器,但我相信RFC 2068說,這都很好:

補丁方法類似於除了實體包含的 列表放在應用PATCH動作之後由Request-URI標識的原始版本的資源 與資源 的期望內容之間的差異。差異列表是由實體的媒體類型(例如, 「application/diff」)定義的格式的 ,並且必須包含足夠的信息以允許 服務器重新創建必要的改變以將原始版本的 版本資源到期望的版本。

因此,更新個人資料123的觀看次數,我想:

PATCH /profiles/123 HTTP/1.1 
Host: www.example.com 
Content-Type: application/x-counters 

views + 1 

x-counters媒體類型(我只是做了)製成的field operator scalar元組多條線。 views = 500views - 1views + 3在句法上都是有效的(但可能在語義上是禁止的)。

我可以理解一些構成另一種媒體類型的皺眉,但我謙卑地建議它比POST/PUT選擇更正確。爲一個字段創建一個資源,使用它自己的URI,尤其是它自己的細節(我沒有真正保留,我擁有的是一個整數)完成,這聽起來對我來說是錯誤和麻煩的。如果我有23個不同的櫃檯需要維護?

+1

由於沒有「應用PATCH操作後所需的資源內容」,因此偏離標準一點點。例如。該實體是要執行的指令,而不是期望的結果。 – Pocketsand 2016-10-15 14:47:39

+0

繼@Pocketsand說過,這種方法是否違反了「統一接口」約束下的「通過表示操作資源」子約束?你應該在哪裏發送你想要查看的資源的表示,而不是發送關於如何操作它的指示。 – dayuloli 2017-06-30 13:09:05

+0

@dayuloli如果你仍在考慮一個解決方案,我已經[添加了答案](https://stackoverflow.com/questions/1426845/incrementing-resource-counter-in-a-restful-way-put-vs-post/44852115#44852115)與我決定一起,它可能會或可能適合您的需求。 – Pocketsand 2017-06-30 17:42:47

0

我認爲Yanic和Rich兩種方法都是相互關聯的。 PATCH不需要是安全的或不具有不確定性的,但可以爲了對併發性更健壯。 Rich的解決方案當然更容易在「標準」REST API中使用。

參見RFC5789

PATCH是既不安全也不冪等由[RFC2616],第 9.1所定義的。

PATCH請求可以以冪等性的方式發出,這也有助於防止在類似的時間幀內在相同資源上的兩個 PATCH請求之間發生衝突的不良結果。 來自多個PATCH請求的衝突可能比 PUT衝突更危險,因爲某些修補程序格式需要從已知基點的 操作,否則它們將破壞資源。

0

評估以前的答案後,我決定PATCH是不妥當的,我的目的,與內容類型擺弄左右爲一個簡單的任務是違反KISS principle的。我只需要增加N + 1,所以我只是這樣做:

PUT /profiles/123$views 
++ 

哪裏++是郵件正文和由控制器解釋爲一個遞增資源的指令。

我選擇$到deliminate資源的字段/屬性,因爲它是一個legal sub-delimiter和,對於我而言,似乎比/這,在我看來,有通行性的氛圍更加直觀。