2011-01-12 104 views
4

我對REST原理相當熟悉,並已閱讀相關論文,維基百科條目,一堆博客文章和有關此主題的StackOverflow問題,但仍未找到常見情況的直接答案:如何獲取REST風格的只讀vs可編輯資源?

我需要請求一個資源來顯示。根據資源的狀態,我需要呈現一個只讀或可編輯的表示形式。在這兩種情況下,我需要獲取資源。我如何構建一個URL來獲取只讀或可編輯版本?

如果我的用戶跟着GET /resource/<id>的鏈接,那應該足以表明他/她需要只讀表示。但是如果我需要將可編輯表單服務器起來,那麼這個URL是什麼樣子的? GET /resource/<id>/edit是顯而易見的,但它在URL中包含一個動詞。改爲GET /resource/<id>/editable解決了這個問題,但在表面上看似膚淺。這一切是否存在 - 將動詞改爲形容詞?

如果我使用POST檢索可編輯版本,那麼如何區分最初檢索它的POST與保存它的POST?我使用POST的(弱)藉口是檢索可編輯版本會導致服務器狀態的變化:鎖定資源。但是,只有我的要求是實施這樣的鎖定,情況並非總是如此。由於同樣的原因PUT失敗,加上PUT在我運行的Web服務器上默認沒有啓用,所以有實際的理由不使用它(和DELETE)。

請注意,即使在可編輯狀態下,我還沒有做任何更改;大概當我再次將資源提交給Web服務器時,我會將其發佈。但爲了讓我可以稍後POST,服務器必須第一個提供一個特定的表示。

我想另一個辦法是必須在集合級別不同的資源: GET /read-only/resource/<id>GET /editable/resource/<id>GET /resource/read-only/<id>GET /resource/editable/<id> ...但是這看起來很醜陋給我。

想法?

回答

6

1)擁有兩個不同的資源是完全有效的,一個用於查看,另一個用於編輯某個域概念。請注意,因爲它們是REST兩個不同的URI,它們是兩種不同的資源。人們經常會將資源與域對象混淆。這就是爲什麼他們最終只能做CRUD。

2)不要太擔心資源的名稱。重要的是你意識到URI指向的是「事物」,「資源」。如果editable而不是edit對你更明顯,那麼就使用它。在你的URL中有一個動詞不會使你的應用程序錯誤,這隻會讓人類的開發人員缺乏可讀性。使用URL中的動詞嘗試和重新定義HTTP方法的語義,現在違反了統一的接口約束。

1

如果我使用POST檢索可編輯版本,那麼如何區分最初檢索它的POST與保存它的POST?

您執行GET(而不是POST)來讀取資源,並POST(或PUT)來寫入資源。

如果您想要對有問題的資源創建鎖定,請使用POST寫入資源(或資源的容器,資源ID編碼在POST的主體中),並讓服務器創建一個鎖作爲新資源,並返回該資源的ID作爲對POST的響應。 (身份驗證問題超出了您的問題或此答案的範圍)

然後解鎖鎖,請在鎖資源上使用DELETE或POST到鎖的容器。

+0

是的,我知道,這就是我的問題的關鍵。我給出了PUT和POST的例子,我認爲這些方法不會起作用,即使我可以找到它們的邊緣語義原因。所以,回到GET。我如何區分可編輯和不可編輯表示? – Val 2011-01-12 01:15:03

+0

他們爲什麼會有不同? (在GET的情況下) – 2011-01-12 01:16:57

+0

他們會有所不同,因爲需要可編輯。這意味着我需要渲染一個表單。我需要知道我是否在表單中呈現請求的資源。我如何知道如何呈現資源? – Val 2011-01-12 01:21:51

2

如何構建URL以獲取只讀或可編輯版本?

這裏存在一個潛在的問題,那就是您首先要構造URL--將ID附加到硬編碼的URL不是REST。 Roy Fielding has written about this very mistake。無論文檔如何提示您編輯資源,都應該包含該資源的可編輯變體的URI。您遵循該URI,無論是/resource/editable還是/editable/resource都不在REST的範圍之內。

+0

是的,這正是會發生的事情。我將從這些資源集合的列表中獲取單個資源,並且該列表將通過基於並表達目標資源狀態的鏈接超鏈接到每個單獨的資源。因此,該集合將具有諸如「GET/resources/resource/23」和「GET/resources/resource/24/edit」的鏈接。只是我讀到的所有東西在網址中都有一個動詞(例如「編輯」)是一種難聞的氣味。我應該克服它嗎? – Val 2011-01-12 01:19:19

+0

菲爾丁有一個博客? +11111111 – Anders 2011-01-12 01:20:37

3

在REST中,編輯現有資源是由客戶端完成GET資源的表示,對錶示進行更改,然後將新表示重新傳遞給服務器。

所以只是閱讀資源的REST客戶端程序會做:

GET http://www.example.com/SomeResource 

並以編輯該資源:

GET http://www.example.com/SomeResource 
... edit it ... 
PUT http://www.example.com/SomeResource 

通常同時更新通過讓處理假設它代表一個更新的狀態,最後一個到達服務器的PUT覆蓋較早的那個。但在你的情況下,你要防範這一點。

仔細考慮@ Jason的建議,爲每個主要資源維護一個可選的並行鎖資源。你的客戶將首先創建鎖,執行編輯,然後刪除鎖。如果隨後進行鎖定的用戶不會保存任何更改,則系統需要自動釋放鎖定。這看起來像:

GET http://www.example.com/SomeResource  
... user presses an edit button ... 
PUT http://www.example.com/SomeResource/lock  
... user edits the resource's representation ... 
PUT http://www.example.com/SomeResource 
DELETE http://www.example.com/SomeResource/lock 

你需要做一些相應的錯誤處理,如果用戶嘗試編輯由其他人鎖定的資源。

聽起來好像你覺得自己受限於HTML的限制。如果使用Restlet(用於Java)等服務器端REST框架,它支持「重載POST」的概念,您可以在其中使用POST,但是可以使用查詢字符串參數(如method = PUT或method = DELETE)。如果你正在編寫你自己的服務器端組件,他們也可以使用這個技巧。

你也可以在HTML級別上玩一些技巧。例如,您的頁面可以具有最初顯示的只讀部分,最初未顯示的輸入窗體。當用戶按下編輯按鈕時,JavaScript會隱藏只讀部分並顯示輸入表單。

請務必閱讀Richardson和Ruby的Restful Web Services(O'Reilly)。這非常有幫助。

3

我不認爲返回表單或只是值取決於REST服務器,而是客戶端的責任。資源是否爲可編輯是資源的屬性,而不是由URL定義的內容。

換句話說:獲取資源的URL是GET /resource/<id>。這有一個屬性可編輯。如果用戶想要表單,它可以從相同的URL檢索資源並填充表單。客戶端可以比PUT/POST更改。

0

我想你的問題可能是「如何識別在PUT動作中使用GET動作返回的只讀表示」?您可以這樣做:

<Root> 
<readonly> 
<p1><p1> 
... 
<readonly> 
<others> 
... 
<others> 
<Root> 

從PUT解析請求XML後,您可以忽略只讀部分並處理其他部分。在響應中,返回200狀態並留言說只讀部分被忽略。 這是您的預期嗎?