2013-01-22 64 views
5

我被要求設計和實現一個RESTful API,並一直在研究最佳實踐,但到目前爲止只有關於資源表示的概念。我發現的大多數可用示例似乎都將重點放在使用一系列GET獲取連接結構的API客戶端上。帶有鏈接的REST資源表示,與PUT和GET兼容

我已經看過:

http://www.restapitutorial.com/media/RESTful_Best_Practices-v1_1.pdf

http://www.youtube.com/watch?v=HW9wWZHWhnI

除其他在線資源(我限制在2個鏈接恕無法一一列舉)。它們都很棒,但並沒有真正解決我的設計問題。

大多數最佳實踐文檔建議兩件事情對我來說在衝突看咯:

1)REST服務應該代表的資源之間的鏈接數據關係

2)從「PUT」請求客戶端應該是完整的表示形式,與服務器上的表示形式相同。

從我的觀點來看,麻煩在於,典型資源中的鏈接以及其他一些屬性是隻讀的,因此無法更新。服務器在裝置上期望它們是原樣的,並且如果它認爲客戶端正在嘗試更新它們,則返回一個錯誤。實際上,當我查看以JSON表示的典型資源時,其中大部分是邏輯上不能/不應該被替換的數據。例如。

{ 
"link": { "rel":"self", "href":"http://example/project/12345" }, 
"team": { 
    "link": { "rel":"self", "href":"http://example/project/12345/team" }, 
    "title": "The project team" 
    }, 
    "title": "The Big Project" 
} 

這裏充其量只有兩個標題文本將寫入到這個資源的客戶機(團隊成員可能是通過團隊鏈接可變)。

所以我應該要求PUT完全按原樣包含所有「鏈接」元素,它們純粹是邏輯的和只讀的(請注意,在示例中,團隊無法重新鏈接,因爲資源定義它作爲項目團隊 - 在這種情況下可以改變,但對於許多具有更嚴格集裝箱的資源類型,這不適用)?

是否存在標準模式或反模式來表示REST中具有多個鏈接的資源?我沒有被要求提供特定的REST變體,比如HATEOAS,儘管我傾向於在可能的情況下以理論上的「正確性」爲目標。換句話說,如果「官方」REST會希望客戶把整個資源,鏈接和所有內容放在一起,那麼這可能是我會做的。

真的很感激一些支持GET和PUT並因此必須處理這個問題的現實世界複雜的非葉REST資源的例子。當我搜索時,我得到很多意見,並且很多例子顯示了GET如何很好地工作。 。 。但到目前爲止,我還沒有看到一個記錄良好的例子,顯示PUT除了一個簡單的葉資源(即不包含任何鏈接,除了可能是自引用外)。

回答

1

您應該在您的媒體類型定義它時放置一個「完整」表示。如果你正在設計你自己的媒體類型,你的規範應該定義哪些部分是可變的,哪些是不可變的。的商事目錄協議,例如,定義a "body" member其旨在包含可變數據:

通常,當主體構件存在,處理器應該期望 身體中存在的值是潛在可變的(通過一個 例如HTTP PUT或POST),並且應該期望身體成員 以外的任何值是不可變的;即(可能)在 插入但不在更新時寫入。服務器是免費的,當然允許或拒絕資源的任何部分的可變性。但是,「身體」成員的存在帶來了關於 數據在該成員之內和之外的可變性的強烈暗示。

這不是一個標準(雖然它對我來說非常有用,我希望它變成一個(眨眼))。請注意,服務器可以隨意使用客戶端發送的表示做任何事情;任何HTTP服務器最強烈的要求是它試圖執行客戶端的意圖(如果能夠和允許的話)。如何以及它在多大程度上確實是您的特定應用程序的關注點,這就是爲什麼您沒有在任何關於它的規格中找到太多東西的原因。

實際上,我沒有發現它對服務器驗證表示的鏈接或其他不可變部分有用;他們完全被忽略。這可能導致客戶決定他們可以省略這些。再次,在實踐中,我沒有發現這是一個問題。

+0

謝謝。我的鉛筆設計包含一個「屬性」部分,它與「身體」成員的想法非常相似。我也在考慮將這些事情分解到他們自己的葉子資源中,這會爲我的設計增加5或6種資源類型(不好),但是相當簡化PUT方法(好) –

3

基本上,GET請求將返回一個序列化爲定義格式的資源,以及關於該資源的元數據(它們一起構成資源的表示形式)。當你放棄一個表示時,它不需要包含元數據,也不需要與原始(或任何後續)GET請求的格式相同。服務器將根據您提供的表示更新資源。

來自HTML的示例是<head><body>元素,它們提供有關資源的元數據和資源表示;和text/htmlapplication/x-www-form-urlencoded內容類型,它們以兩種不同的格式傳輸資源表示,前者與元數據,後者沒有。在發佈後獲取資源時,您不希望收到application/x-www-form-urlencoded格式的數據!

我不確定你的意思是「REST變種」。只有一個REST。如果您指的是其他基於HTTP的API,請不要將它們稱爲REST。有關API樣式的更多詳細信息,請參見Classification of HTTP-based APIs

最後,您要求提供非葉PUT請求的示例。我不知道你所說的無葉的意思是什麼,我能想到的兩種類型:

  1. 集合
  2. 子資源

集合 比方說,你有車目錄,可在/cars。如果您決定要清除所有車輛,則可以執行DELETE /cars/1,DELETE /cars/2等等,或者您可以選擇PUT /cars,其中包含空的車身或沒有內容的陣列。後者顯然會更有效率。

子資源 繼續這個主題,讓我們說,有一輛車,/cars/1這是這樣表示:

{ 
    "model":"Model-T", 
    "mfgr":"Ford", 
    "colour":"black" 
} 

現在,你可能希望允許通過網址,這樣可以訪問這些字段作爲/cars/1/mfgr,其將返回Ford或者可能{"mfgr":"Ford"}。現在URL /cars/1代表一個非葉資源。但是,在URL中添加新的表示形式仍然沒有問題。因此,這也會更新子資源URL的值。

最後,您可能需要查看HAL格式以通過JSON傳輸超文本。

+0

謝謝。對於我來說,HAL看起來像一個可行的選項(通過ROAR gem),因爲我很可能會選擇Ruby的葡萄珠寶來實現API。 –

+0

很好的答案。我喜歡鏈接中的API分類的初始成本,維護成本,演進成本。 – codeasone