圖 2:0 級交互示例

假設我想預約醫生。我的預約軟件首先需要知道醫生在特定日期有哪些空閑時段,因此它會向醫院預約系統發出請求以獲取該信息。在 0 級場景中,醫院將在某個 URI 上公開服務端點。然后,我將包含我的請求詳細信息的文檔發布到該端點。POST /appointmentService HTTP/1.1 [各種其他標頭]

然后服務器將返回一個文檔,向我提供以下信息HTTP/1.1 200 OK [各種標頭]

我在這里使用 XML 作為示例,但內容實際上可以是任何內容:JSON、YAML、鍵值對或任何自定義格式。

我的下一步是預約,我可以通過將文檔發布到端點來再次進行預約。POST /appointmentService HTTP/1.1 [各種其他標頭]

如果一切順利的話,我會收到回復,告知我預約已經完成。HTTP/1.1 200 OK [各種標頭]

如果出現問題,比如說其他人在我之前進入,那么我就會在回復正文中收到某種錯誤消息。HTTP/1.1 200 OK [各種標頭] Slot 不可用

到目前為止,這是一個簡單的 RPC 樣式系統。它很簡單,因為它只是來回傳遞普通的舊 XML (POX)。如果您使用 SOAP 或 XML-RPC,它基本上是相同的機制,唯一的區別是您將 XML 消息包裝在某種信封中。

Level 1 級 – 資源

在 RESTful成熟度模型 中實現 Rest 榮耀的第一步是引入資源。因此,現在我們不再將所有請求發送到單個服務端點,而是開始與各個資源對話。

圖 3:第 1 級添加資源

因此,通過我們的初步查詢,我們可能會獲得特定醫生的資源。POST /doctors/mjones HTTP/1.1 [各種其他標頭]

回復帶有相同的基本信息,但是每個插槽現在都是可以單獨尋址的資源。HTTP/1.1 200 OK [各種標頭]

通過特定資源預約意味著發布到特定的時間段。POST /slots/1234 HTTP/1.1 [各種其他標頭]

如果一切順利的話,我會收到與之前類似的答復。HTTP/1.1 200 OK [各種標頭]

現在的區別是,如果有人需要對預約做任何事情,比如預約一些測試,他們首先獲取預約資源(可能具有類似的 URI), http://royalhope.nhs.uk/slots/1234/appointment然后發布到該資源。

對于像我這樣的對象迷來說,這就像對象身份的概念。我們不是調用以太中的某個函數并傳遞參數,而是調用一個特定對象上的方法,為其他信息提供參數。

Level 2 級——HTTP 動詞

我在級別 0 和 1 中的所有交互中都使用了 HTTP POST 動詞,但有些人會改用或同時使用 GET。在這些級別上,這并沒有太大區別,它們都被用作隧道機制,允許您通過 HTTP 隧道進行交互。RESTful成熟度模型 的級別 2 不再這樣做,而是盡可能接近 HTTP 本身的使用方式來使用 HTTP 動詞。

圖 4:第 2 級添加了 HTTP 動詞

對于插槽列表,這意味著我們要使用 GET。GET /doctors/mjones/slots?date=20100104&status=open HTTP/1.1 主機:royalhope.nhs.uk

答復與 POST 相同HTTP/1.1 200 OK [各種標頭]

在第 2 級,對于此類請求,使用 GET 至關重要。HTTP 將 GET 定義為安全操作,即它不會對任何事物的狀態做出任何重大更改。這使我們能夠以任意順序安全地調用任意次數的 GET,并且每次都獲得相同的結果。這樣做的一個重要結果是,它允許請求路由中的任何參與者使用緩存,這是使 Web 性能良好的關鍵要素。HTTP 包括各種支持緩存的措施,通信中的所有參與者都可以使用這些措施。通過遵循 HTTP 規則,我們能夠利用該功能。

要預約,我們需要一個可以改變狀態的 HTTP 動詞,即 POST 或 PUT。我將使用之前使用的相同 POST。POST /slots/1234 HTTP/1.1 [各種其他標頭]

這里我想討論的是使用 POST 和 PUT 之間的權衡,也許有一天我會寫一篇關于它們的文章。但我想指出的是,有些人錯誤地將 POST/PUT 與創建/更新對應起來。它們之間的選擇與此完全不同。

即使我使用與第 1 級相同的帖子,遠程服務的響應方式也存在另一個顯著差異。如果一切順利,服務將回復響應代碼 201,以表明世界上有新的資源。HTTP/1.1 201 創建 位置:slots/1234/appointment [各種標題]

201 響應包含一個帶有 URI 的位置屬性,客戶端可以使用該 URI 在將來獲取該資源的當前狀態。此處的響應還包括該資源的表示,以便現在為客戶端節省額外的調用。

如果出現問題,例如其他人預訂了會議,則還會有其他區別。HTTP/1.1 409 沖突 [各種標頭]

此響應的重要部分是使用 HTTP 響應代碼來指示出現問題。在這種情況下,409 似乎是一個不錯的選擇,它表示其他人已經以不兼容的方式更新了資源。在級別 2 中,我們明確使用某種錯誤響應,而不是使用返回代碼 200 但包含錯誤響應。由協議設計者決定使用什么代碼,但如果出現錯誤,應該有一個非 2xx 響應。級別 2 引入了使用 HTTP 動詞和 HTTP 響應代碼。

這里出現了不一致的情況。REST 的倡導者談論使用所有 HTTP 動詞。他們還通過說 REST 試圖從 Web 的實際成功中學習來證明他們的方法是正確的。但萬維網在實踐中并不經常使用 PUT 或 DELETE。有合理的理由更多地使用 PUT 和 DELETE,但 Web 的存在證明不是其中之一。

網絡存在所支持的關鍵元素是安全(例如 GET)和非安全操作之間的嚴格分離,以及使用狀態代碼來幫助傳達您遇到的錯誤類型。

Level 3 級——超媒體控制

RESTful成熟度模型 的最后一個層次是HATEOAS(超媒體控制)這個難聽的縮寫詞。它解決了如何從空位列表到知道如何預約的問題。

圖 5:第 3 級添加超媒體控件

我們從在第 2 級中發送的相同的初始 GET 開始GET /doctors/mjones/slots?date=20100104&status=open HTTP/1.1 主機:royalhope.nhs.uk

但回應有新的元素HTTP/1.1 200 OK [各種標頭]

每個時段現在都有一個鏈接元素,其中包含一個 URI,用于告訴我們如何預約。

超媒體控件的意義在于它們告訴我們下一步可以做什么,以及我們需要操縱的資源的 URI 才能做到這一點。我們不必知道在哪里發布預約請求,響應中的超媒體控件會告訴我們如何做。

POST 將再次復制 2 級POST /slots/1234 HTTP/1.1 [各種其他標頭]

答復包含許多超媒體控件,用于控制接下來要執行的不同操作。HTTP/1.1 201 創建 位置:http://royalhope.nhs.uk/slots/1234/appointment [各種標題]

超媒體控件的一個明顯好處是,它允許服務器更改其 URI 方案而不會破壞客戶端。只要客戶端查找“addTest”鏈接 URI,服務器團隊就可以處理除初始入口點之外的所有 URI。

另一個好處是它可以幫助客戶端開發人員探索協議。這些鏈接為客戶端開發人員提供了下一步可能的操作的提示。它并沒有提供所有的信息:“self”和“cancel”控件都指向同一個 URI – 他們需要弄清楚一個是 GET,另一個是 DELETE。但至少它為他們提供了一個起點,讓他們知道要考慮什么才能獲得更多信息,并在協議文檔中尋找類似的 URI。

同樣,它允許服務器團隊通過在響應中添加新鏈接來宣傳新功能。如果客戶端開發人員密切關注未知鏈接,這些鏈接可能會引發進一步的探索。

對于如何表示超媒體控件,沒有絕對的標準。我在這里所做的是使用 REST 實踐團隊的當前建議,即遵循 ATOM(RFC 4287)。我使用一個元素,該元素具有一個uri 目標 URI 的屬性和一個rel用于描述關系類型的屬性。眾所周知的關系(例如self對元素本身的引用)是裸的,任何特定于該服務器的關系都是完全限定的 URI。ATOM 指出,眾所周知的鏈接關系的定義是鏈接關系注冊表。在我寫這些時,這些僅限于 ATOM 所做的事情,ATOM 通常被視為 3 級 restfulness 的領導者。

一站搜索、試用、比較全球API!
冪簡集成已收錄 4968種API!
試用API,一次比較多個渠道