歡迎光臨
每天分享高質量文章

RESTful 架構基礎

(給ImportNew加星標,提高Java技能)

 

來自:唐尤華

譯自:https://dzone.com/refcardz/rest-foundations-restful

 

REST(Representational State Transfer)架構風格是一種世界觀,把資訊提升為架構中的一等公民。透過 REST 可以實現系統的高效能、可伸縮、通用性、簡單性、可修改性和可擴充套件等特性。這篇文章解釋了主要的 HTTP 操作,對 HTTP 響應碼進行描述,併列舉相關開發庫和框架。此外,本文還提供了額外的資源,對每個主題進行了更深入的探討。

 

1. 簡介

 

REST 架構風格不是一種可以購買的技術,也不是一個可以新增到軟體開發專案中的開發庫。首先也是最重要的,REST 是一種世界觀,把將資訊提升為構建架構中的一等公民。

 

Roy Fielding 的博士論文“架構風格和基於網路的軟體架構設計”介紹和整理了“RESTful”系統的思想和相關術語。這是一篇學術論文,雖然使用正式語言,但是仍然易於理解並且提供了實踐基礎。

 

總結一下,RESTful 透過體系結構的特定選擇能從部署的系統中獲得理想特性。儘管這種風格定義的約束細節並沒有為所有場合設計,但是的確可以廣泛適用。

 

由於 Web 對消費者偏好有多重影響,REST 風格的倡導者鼓勵企業組織在其邊界內使用相同原則,就像他們在面向外部客戶的網頁上做的那樣。本文將討論現代 REST Web 實現中的基本約束和屬性。

 

1.1 基礎概念

 

REST 表示什麼含義?以無狀態方式傳輸、訪問和操作文字資料。當正確部署後,REST 為網際網路上不同應用程式之間提供了一致的互操作性。無狀態(stateless)這個術語至關重要,它使得應用程式可以用不可知的方式進行通訊。RESTful API 透過統一資源定位符地址(URL)公開服務。URL 名稱將資源的區分為接受內容或傳回內容。RFC 1738中定義了 URL scheme,可以在這裡找到: https://tools.ietf.org/rfc/rfc1738.txt

 

RESTful URL 類似於下麵這個 library API:

 

http://fakelibrary.org/library

 

實際公開的不一定是某種任意的服務,而是代表對消費者有價值的資訊資源。URL 作為資源控制代碼,可以請求、更新或刪除內容。

 

開始把服務釋出到某個地方,然後開始與 REST 服務進行互動。傳回的內容可能是 XML、JSON 格式,或者更確切地說是像 Atom 或自定義 MIME 型別等超媒體格式。雖然一般建議盡可能重用現有的格式,但是對正確設計的媒體型別正在變得越來越寬容。

 

需要請求資源的時候,客戶機會發一個超文字傳輸協議(HTTP)GET 請求,例如在瀏覽器中鍵入一個 URL 然後點選回車,選擇書簽,或者點選錨取用連結。

透過程式設計方式與 RESTful API 互動,有數十個客戶端 API 或工具可供選擇。使用 curl 命令列工具,可以輸入以下命令:

 

$ curl http://fakelibrary.org/library

 

上面的命令使用預設格式,但你可能不需要這種格式的資訊。幸運的是 HTTP 有一種機制,可以指定傳回信息的格式。在請求中指定 “Accept” 頭,如果伺服器支援這種格式,會以指定的格式傳回。這個過程稱為內容協商,這是 HTTP 中未被充分利用的功能之一,可以使用一個類似於上面例子中的 curl 命令來指定:

 

$ curl –H "Accept:application/json" http://fakelibrary.org/library

 

由於資源名稱與內容格式是獨立的,從而讓請求不同格式資訊成為可能。雖然 REST 中的 “R” 的含義是 “表現”而非“資源”,但是應該在構建系統時允許客戶端指定請求的內容格式,請牢記這一點。在我們的例子中 library API 可能包含以下 URL:

 

  • http://fakelibrary.org/library:圖書館基本資訊,搜尋圖書、DVD等相關資源基本功能的連結。
  • http://fakelibrary.org/book:存放書籍的“資訊空間”。從概念上說,這裡可能會存放所有的書籍。顯然,如果這個問題得到解決,我們不會希望傳回所有圖書,而是希望透過類別、搜尋關鍵詞等來檢索圖書。
  • http://fakelibrary.org/book/category/1234:在書籍的資訊空間裡,我們可以指定類別瀏覽,例如成人小說、兒童書籍、園藝書籍等。使用杜威十進製圖書分類法是可行的,但我們也可以想象自定義分組。問題的關鍵在於,這種“資訊空間”可能是無限的,而且可能收到人們實際關心的資訊型別影響。
  • http://fakelibrary.org/book/isbn/978-0596801687:提到某本具體的書,應該包括書名、作者、出版商、系統中的複製數、可用複製數等資訊。

 

譯註: 杜威十進製圖書分類法由美國圖書館專家麥爾威·杜威發明,於1876年首次發表,歷經22次的大改版。該分類法以三位數字代表分類碼,共可分為10個大分類、100個中分類及1000個小分類。

 

就圖書館使用者而言,上面提到的這些 URL 可能就是隻讀的,但是圖書館員使用應用程式時實際上可以操作這些資源。

 

例如新增一本新書,可以向 main/book 地址 POST 一個 XML。 使用 curl 提交,看起來可能像這樣:

 

$  curl –u username:password -d @book.xml -H "Content-type: text/xml" http://fakelibrary.org/book

 

此時,伺服器可能會對提交的內容進行校驗,建立與圖書相關的記錄,並傳迴響應程式碼201——表示已建立新資源。新資源的 URL 可以在響應的 Location 頭中找到。

 

RESTful 請求一個重要特性:每次請求都包含了充足的狀態資訊來響應請求。這為伺服器的可見性和無狀態創造了條件,併為擴充套件系統和識別傳送的請求內容提供了理想特性。對於快取結果也非常有幫助。伺服器地址和請求狀態組合成可計算的 hash 鍵值,並形成一個結果集:

http://fakelibrary.org + /book/isbn/978-0596801687

 

接下來我們會先介紹 GET 請求。客戶端在需要時發出 GET 請求獲取指定資源。客戶端可以在本地快取請求結果,伺服器可以在遠端快取結果,系統的中間層可以在請求鏈路中間快取結果。這是一個與具體應用程式無關的特性,可以加入系統設計中。

 

正因為可以操作資源,也就意味著並不是每個人都可以這樣做。我們完全可以建立一個防護模型,要求使用者在操作前驗證身份,證明他們具有該操作的授權。在本文的最後,將提供一些提升 RESTful 服務安全性的內容。

 

2. REST 和 SOAP 比怎麼樣?

 

SOAP:簡單物件訪問協議(Simple Object Access Protocol)。是交換資料的一種協議規範,是一種輕量的、簡單的、基於XML的協議。一條 SOAP 訊息就是一個普通的 XML 檔案,包含必需的 Envelope 元素、可選的 Header 元素、必需的 Body 元素和可選的 Fault 元素。

 

把 REST 與 SOAP 劃等號是錯誤的。在這兩者之間進行比較,帶來的困擾遠多於好處。簡單來說,它們不是一回事。儘管可以用這兩種方法解決許多架構問題,但是它們不能相互替換。

 

這種混淆很大程度上源於對 “REST 是透過 URL 呼叫 Web 服務”這句話的誤解。這種觀點與 RESTful 架構的功能相距甚遠。如果不全面深入理解 RESTful 的架構實現,就很容易誤解 REST 實踐的本意。

 

利用 REST 的最佳方式,是將生產和消費過程中的資訊與技術分離實現解耦,進而更好地管理系統,讓架構具備以下特性:

 

  • 高效能
  • 可擴充套件
  • 通用
  • 簡潔
  • 可修改
  • 可擴充套件

 

這並不是說,基於 SOAP 構建的系統不能具備上述特性。而是當技術、組織或過程的複雜性造成不能在單個事務中完成請求的生命週期時,這種情況 SOAP 能夠發揮最佳效果。

 

3. Richardson 成熟度模型

 

Leonard Richardson 引入了一種成熟度模型,部分闡述了 SOAP 與 REST 之間的區別,並提供一種對不同型別的系統進行分類的框架。許多人不恰當地稱之為 “REST”。可以將這種分類看作系統中不同 Web 技術元件緊密程度的度量標準:包括資訊資源、HTTP 作為應用層協議和作超媒體作為控制媒介。

 

 

稱其為“成熟度模型”似乎意味著應該只構建“成熟度”最高的系統。這種看法是不合適的。第2級是有價值的,從2級向3級轉變通常只是採用了一種新的 MIME 型別。然而,從0級到3級的轉變要困難得多,因此增量式升級轉變通常也會增值。

 

首先,確定希望公開哪些資訊資源。採用 HTTP 作為處理這些資訊資源的應用協議,包括內容協商。接下來,當一切就緒時,使用基於超媒體的 MIME 型別,這樣就可以充分享受 REST 的好處了。

 

4. 動詞

 

動詞是用來與伺服器資源互動的方法或操作。 RESTful 系統中有限的動詞讓剛接觸該的使用者感到困惑和沮喪。看似武斷和不必要的約束,目的是鼓勵以應用程式無關的形式提供可預測的行為。透過明確、清晰地定義這些動詞的行為,客戶端可以在網路中斷或故障時自主處理。

 

精心設計的 RESTful 系統主要使用4個 HTTP 動詞。

 

4.1 GET

 

GET 請求是最常用的 Web 動詞。 GET 請求將命名資源從伺服器傳輸到客戶端。儘管客戶端不需要知道請求的資源內容,但是請求傳回的結果是帶元資料標記的位元組流,這表明客戶端應該知道如何解釋資源。 在 Web 中通常用 “text/html” 或 “application/xhtml+xml” 表示。正如之前提到的那樣,只要伺服器支援,客戶端可以透過內容協商提前指定請求的傳回格式。

 

GET 請求關鍵點之一,不要修改伺服器端的任何內容。這是一個基本的安全要求,也是不熟悉 REST 的開發者犯的最大錯誤之一。你可能會遇到這樣的 URL:

 

 

http://example.com/res/action=update?data=1234

 

 

不要這樣做! 由於 GET 請求安全性允許快取請求,這會讓正在構建的 RESTful 系統陷入混亂。 GET 請求也意味著冪等性,即多次請求不會對系統產生任何影響。這是基於分散式基礎設施的一個重要特性。如果進行 GET 請求時被打斷,由於冪等性,客戶端可以再次發起請求。這點非常重要。在設計良好的基礎結構中,客戶端可以從任意應用程式發起請求。雖然一定會有與應用程式相關的特定行為,但是加入與應用程式無關的行為越多,系統就會越有彈性,也更容易維護。

 

4.2 POST

 

在辨別 POST 和 PUT 動詞意圖的時候,情況開始變得不那麼清晰。根據定義,二者似乎都可以被客戶端用來建立或更新伺服器資源,然而它們的用途各有不同。

 

當無法預測請求建立的資源的標識時,客戶端會使用 POST 請求。在新增僱員、下訂單或提交表單的時候,我們無法預測伺服器將如何命名正在建立的資源。這就是為什麼將資源提交給類似 Servlet 這樣的程式處理。接下來,伺服器會接受請求、校驗請求、驗證使用者憑據等。成功處理後,伺服器將傳回 201 HTTP 響應程式碼,其中包含一個 “Location” 頭,代表新建立的資源的位置。

 

註意: 有些人將 POST 視為建立資源的 GET 會話。他們會對建立的資源透過 body 傳回200,而不是傳回201。這似乎是避免二次請求的一種快捷方式,但是這種做法混合了 POST 和 GET,讓快取資源的潛在影響變得微妙。儘量避免因為走捷徑而犧牲大局。短期看這似乎是值得的,但隨著時間的推移,這些捷徑疊加起來可能會帶來不利的影響。

 

POST 動詞的另一個主要用途是“追加(Append)”資源資訊,即增量編輯或部分更新,而不是提交完整的資源。這裡應使用 PUT 操作。對已知資源使用 POST 更新,可用於向訂單新增新送貨地址或更新購物車中某個商品的數量。

 

由於是更新資源的部分資訊,POST 既不安全也不冪等

 

POST 的最後一種常見用法是提交查詢。將查詢的內容或表單內容進行 URL 編碼後提交給服務執行查詢。通常可以直接傳回 POST 結果,因為沒有與查詢相關的標識。

 

註意: 建議將這樣的查詢轉換為資訊資源本身。如果採用 POST 查詢,可以考慮採用 GET 請求,後者支援快取。你可以與其他人分享這個連結。

 

4.3 PUT

 

由於 HTML 表單目前還不支援 PUT,許多開發人員基本上會忽略 PUT 動詞。然而,PUT 有一個重要作用並且是 RESTful 系統完整願景的一部分。

 

客戶端可以向指定 URL 發 PUT 請求,伺服器用請求中的資料執行改寫操作。PUT 請求在某種程度上是等冪的,而 POST 更新不是。

 

如果客戶端在 PUT 改寫請求時被打斷,由於重新傳送改寫操不會造成任何後果,因此可以再次傳送。客戶端具備管理狀態能力,所以直接重發改寫命令即可。

 

註意: 這種協議層處理並不意味著要取消更高階別(如應用層)的事務,但是同樣地,它也是一種體系結構上理想的屬性,可以在應用層以下使用。

 

如果客戶端能夠提前瞭解資源的標識,那麼 PUT 也可用於建立資源。正如我們在 POST 部分中討論的那樣,通常不會出現這種情況。但是如果客戶端能夠控制伺服器端資訊空間,那麼這種操作也是合理的。

 

4.4 DELETE

 

在公共網路上 DELETE 動詞沒有被廣泛使用(謝天謝地!)。然而,對於控制資訊空間非常有用,它是資源生命週期中非常有用的一部分。

 

DELETE 請求意在實現等冪。可能由於網路故障 DELETE 請求被打斷,這時我們希望客戶端繼續嘗試。第一次請求無論成功與否,資源都應該傳回204(無指定內容)。對之前已刪除的資源或不存在的資源可能需要一些額外處理,兩種情況都應該傳回404。一些安全策略要求為不存在的和已刪除的資源傳回404,這樣 DELETE 請求就不會洩漏有關資源是否存在的資訊。

 

還有另外三個沒有廣泛使用但是有價值的動詞。

 

4.5 HEAD

 

HEAD 動詞用來請求資源,但不實際檢索。客戶端可以透過 HEAD 檢查資源是否存在,並檢查資源相關的元資料。

 

4.6 OPTIONS

 

OPTIONS 動詞也可以用來查詢伺服器相關資源的情況,方法是詢問哪些其它動詞可用於該資源。

 

4.7 PATCH

 

最新的動詞 PATCH 直到2010年才正式採納為 HTTP 的一部分。旨在提供一種標準化方式來表示部分更新。PATCH 請求透過標準格式讓互動的意圖更明確。這是推薦使用 PATCH 而非 POST 的原因,儘管 POST 可以用於任何事情。 IETF 釋出了 RFC 檔案,定義用於 PATCH 操作的 XML 和 JSON。

 

如果客戶端 PATCH 請求的 essay-header 中帶 If-Match,則此部分為冪等更新。可以重試中斷的請求,因為如果第一次請求成功,那麼 If-Match essay-header 會不同於新狀態。如果相同,則未處理原始請求可應用 PATCH。

 

5. 響應碼

 

HTTP 響應碼為我們在客戶端和伺服器之間的對話提供了豐富的請求狀態資訊。大多數人只熟悉一般意義上的200、403、404或者500,但是還有更多有用的程式碼可供使用。這裡表格並不全面,但是它們涵蓋了許多在 RESTful 環境中應該考慮使用的最重要程式碼。數字可按照以下類別分組:

 

  • 1XX:資訊類
  • 2XX:操作成功
  • 3XX:重定向
  • 4XX:客戶端錯誤
  • 5XX:伺服器錯誤

 

第一組響應碼表明客戶端的請求格式正確且處理成功。具體操作如下表所示:

 

表1 成功的客戶端請求

 

表2 — 客戶端重定向請求

 

表3中的響應程式碼表示客戶端請求無效,如果條件不發生變化,重新請求仍無法處理。這些故障可能有請求格式錯誤、未授權的請求、請求的資源不存在等。

 

表3 客戶端請求錯誤

 

最後,表4中的響應程式碼表示伺服器暫時無法處理客戶端請求(可能仍然無效)。客戶端應當在將來的某個時候重新請求。

 

表4 伺服器處理請求錯誤

 

服務根據其自身功能要求具有不同程度的可擴充套件性。

 

註意: 試試響應程式碼418,它會傳回簡潔有力的回覆:”我是一個茶壺。”

 

5.1 REST 資源

 

5.1.1 論文

 

Fielding 博士的論文《架構的風格與基於網路的軟體架構設計》是對 RESTful 思想的主要介紹:http://www.ics.uci.edu/~fielding/pubs/dissertation/top.htm

 
5.1.2 RFC 規範

 

REST 常見用法的技術規範由**國際網際網路工程任務組(IETF)定義,按照請求評議(RFC)**流程完善。規範由數字定義,並隨著時間推移不時更新版本,以替換已經過時的檔案。目前,這裡有最新的相關 RFC 檔案。

 

5.1.2.1 URI

 

RFC 3986定義了 URI 命名方案的通用語法。URI 是一種命名方案,包含了對其他如網址、支援名字子空間等編碼方案。網址:http://www.ietf.org/rfc/rfc3986.txt>

 
5.1.2.2 URL

 

Url 是 URI 的一種形式,其中嵌入了充足的資訊(通常是訪問方案和地址),用於解析和定位資源統一資源定位符。 網址:http://www.ietf.org/rfc/rfc1738.txt

 
5.1.2.3 IRI
 

國際化資源識別符號(IRI)在概念上是一個用 Unicode 編碼的 URI,用於在 Web 上使用的識別符號中支援世界上各種語言的字元。 IETF 選擇建立一個新的標準,而不是改變 URI 方案本身,以避免破壞現有的系統並明確區分這兩種方法。那些支援 IRI 的人故意這樣做。 還定義了在 IRI 和 URI 之間進行轉換的對映方案。 網址

 

5.1.2.4 HTTP

 

HTTP 1.1版本定義了一個應用程式協議,用於操作通常以超媒體格式表示的資訊資源。雖然它是一個應用級協議,但通常不與應用程式系結,由此產生了重要的體系結構優勢。 大多數人認為 HTTP 和超文字標記語言文(HTML)就是“Web”,但是 HTTP 在非面向檔案的系統開發中也很有用。 網址: http://www.ietf.org/rfc/rfc2616.txt

 

5.1.2.5 PATCH 格式

 

JavaScript 物件表示法(JSON)Patch 網址:https://www.ietf.org/rfc/rfc6902.txt
XML Patch 網址:https://www.ietf.org/rfc/rfc7351.txt

 

5.2 描述語言

 

人們對使用各種語言來描述 API 非常感興趣,透過描述語言可以更容易地編寫客戶端和伺服器檔案,甚至生成骨架程式碼。一些比較流行、有趣的描述語言包括:

 
5.2.1 RAML

 

RAML 是一種 YAML/JSON 語言,可以定義2級成熟度的 API。它支援可重用樣式和特性,透過樣式和特性實現功能 API 設計的標準化。網址:http://raml.org

 
5.2.2 Swagger

 

Swagger 是另一種 YAML/JSON 語言,支援定義2級成熟度的 API。它包含程式碼生成器、編輯器、 API 檔案視覺化功能,能夠與其他服務整合的。 網址:http://swagger.io

 
5.2.3 Apiary.io

 

Apiary.io 是一個協作式的託管站點。它支援 Markdown 格式的 API 檔案,可以圍繞設計過程進行社交,並且支援模擬資料的託管實現,以便於在 API 實現之前對其進行測試。 網址:http://apiary.io

 

5.2.4 Hydra-Cg

 

Hydra-Cg 是一種超媒體描述語言,透過像 JSON-LD 這樣的標準方便地實現資料關聯和並其它資料源的互動。網址:http://www.hydra-cg.com

 

5.3 實現

 

有一些用於構建、生成和使用 RESTful 系統的庫和框架。雖然任何 Web 伺服器都可以配置成提供 REST API,但有了這些框架、庫和環境可以讓過程變得更容易。

 

以下概述了一些主流的環境:

 
5.3.1 JAX-RS

 

JAX-RS 規範為 JEE 環境增加了對 REST 的支援。網址:https://jax-rs-spec.java.net

 

5.3.2 Restlet

 

Restlet API 是構建用於生產和消費 RESTful 系統的 Java API 先行者之一。它專註於為客戶端和伺服器生成一些非常乾凈、強大的 API。

 

Restlet Studio 是一個免費工具,能夠在 RAML 和基於 swagger 的 API 描述之間進行轉換,支援 Restlet、 Node 和 JAX-RS 伺服器和客戶端的骨架和 Stub 程式碼。網址:http://restlet.org

 

5.3.3 NetKernel

 

Netkernel 是一個比較有趣的 RESTful 系統。它基於微核心,是支援各種架構風格環境的代表。Netkernel 受益於在軟體體系結構中採用 Web 的經濟屬性。你可以把它想象成“在內部引入 REST”。雖然任何基於 REST 的系統在外面看起來都一樣,但在執行環境內部 NetKernel 看起來也一樣。網址:http://netkernel.org

 
5.3.4 Play

 

兩個主要的 Scala REST 框架之一。網址:https://www.playframework.com

 
5.3.5 Spray

 

兩個主要的 Scala REST 框架之一。它設計成配合 Akka actor 模型一起工作。網址:http://spray.io

 

5.3.6 Express

 

兩個主要的 Node.js REST 框架之一。網址:http://expressjs.com

 

5.3.7 hapi

 

兩個主要的 Node.js REST 框架之一。網址:http://hapijs.com

 

5.3.8 Sinatra

 

Sinatra 是一個領域特定語言(DSL),用來在 Ruby 中建立 RESTful 應用程式。網址:http://www.sinatrarb.com

 

5.4 客戶端

 

透過瀏覽器呼叫 REST API 是可行的,但是還有其它客戶端可用於測試和構建面向資源的系統。

 

5.4.1 curl

 

curl 是流行的庫和命令列工具之一,支援在各種資源上呼叫各種協議。網址:https://curl.haxx.se

 
5.4.2 httpie

 

httpie 是一個非常靈活和易用的客戶端,支援透過 HTTP 與資源進行互動。網址:https://httpie.org

 
5.4.3 Postman

 

健全的 API 測試需要能夠捕獲和重播請求,支援各種身份驗證和授權方案等功能。以前的命令列工具允許這樣做,但 Postman 是一個較新的桌面應用程式,讓這些工作對於開發團隊來說變得更容易。網址:https://www.getpostman.com

 

6. 書籍

 

  • “RESTful Web APIs”:Leonard Richardson、Mike Amundsen 和 Sam Ruby,2013,O’Reilly 出版社
  • “RESTful Web Services Cookbook”:Subbu Allamaraju,2010,O’Reilly 出版社
  • “REST in Practice”:Jim Webber、Savas Parastatidis 和 Ian Robinson,2010,O’Reilly 出版社。中文版《REST實戰(中文版)》
  • “Restlet in Action” by Jerome Louvel and Thierry Boileau,2011,Manning 出版社
  • “Resource-Oriented Architecture Patterns for Webs of Data (Synthesis Lectures on the Semantic Web: Theory and Technology)”:Brian Sletten,2013,Morgan & Claypool

    贊(0)

    分享創造快樂