我所理解的RESTful Web API [Web標準篇]
REST不是一個標準,而是一種軟件應用架構風格。基於SOAP的Web服務采用RPC架構,如果說RPC是一種面向操作的架構風格,而REST則是一種面向資源的架構風格。REST是目前業界更為推崇的構建新一代Web服務(或者Web API)的架構風格。由於REST僅僅是一種價格風格,所以它是與具體的技術平臺無關的,也就是說采用REST架構的應用未必一定建立在Web之上,所以在正式介紹REST之前,我們先來簡單認識一下Web。
目錄
一、TCP/IP與HTTP
二、Web資源
媒體類型
URI、URL和URN
三、HTTP事務
HTTP方法
響應狀態碼
四、HTTP報文
如果要問大家這樣一個問題:“在過去半個世紀中,哪種信息技術對人類的影響最為深遠?”,我想很多人的答案是Web(World Wide Web、WWW、W3或者萬維網),因為它改變了我們的生活方式和思維方式。如果各位閱讀過W3C介紹WWW的官方文檔(“http://www.w3.org/WWW/”),應該對它的第一句話記憶猶新——“The World Wide Web (known as "WWW‘, "Web" or "W3") is the universe of network-accessible information, the embodiment of human knowledge”。如果將這句話翻譯成簡潔的中文,就是“Web是(網絡)信息的來源,知識的化身”。
Web為我們提供了一種利用HTTP協議獲取和操作網絡資源的方式,這些將Web服務器作為宿主的資源不僅僅包含像文字和圖片這些傳統的信息載體,還包含音頻和視頻這些多媒體信息。Web的核心主要體現在三個方面,即HTTP、超文本(Hypertext)和超媒體(Hypermedia)[1],超文本和超媒體規範了網絡信息的表現形式,而HTTP則提供了網絡訪問的標準協議。接下來我們就以圍繞著HTTP對Web作一下基本的介紹。
一、TCP/IP與HTTP
TCP/IP是以IP和TCP協議為核心的一整套網絡協議的總稱,所以有時候我們也稱其為TCP/IP協議簇。毫不誇張地說,TCP/IP支撐著整個互聯網,因為它就是互聯網采用的網絡協議。TCP/IP協議簇劃分為如右圖所示的4個層次[2](應用層、傳輸層、網絡層和鏈路層),構成整個協議簇的各個子協議處於相應層次中。
既然將整個協議簇命名為TCP/IP,那麽IP和TCP自然就是其中最為核心的兩個協議了。處於網絡層的IP協議提供的IP數據報傳輸是不可靠的,因為它只承諾盡可能地將數據報發送出去,但不能保證發送的數據報能夠成功地抵達目的地。IP協議的不可靠性還體現在它不能檢測數據在傳輸過程中是否發生了改變,也就是說數據的完整性得不到保證。IP協議是一個無連接(Connectionless)的網絡協議,每次數據報的處理對它來說均是獨立的,因此IP協議也不能提供針對有序傳輸(數據接收的順序與發送的順序一致)的保證。
雖然IP協議只能提供不可靠的數據傳輸,同時有序傳輸也得不到保證,但是建立在它之上的傳輸層協議TCP有效地解決了這兩個問題。TCP是一個基於連接的協議,數據交換雙方在進行報文傳輸之前需要建立連接,報文傳輸結束之後需要關閉連接。這是一個雙工(Duplex)連接,數據交換的雙工均可以利用它向對方發送數據。
TCP利用“接收確認”和“超時重傳”機制確保了數據能夠成功抵達目的地。具體來說,接收方在成功接收到數據之後會回復一個確認消息。發送方在本地具有一個存放尚未得到確認的已發消息的緩沖區,如果發送方在一個設定的時限內沒有接收到針對某個已發報文的確認消息,它會從該緩存區中選擇對應的報文進行重新發送。在接收到確認之後,相應的報文會從緩存區中移除。
為了解決有序傳輸的問題,發送方會為每個報文進行編號,報文的序號體現了它們被發送的順序。接收端在接收到某個報文之後,它會利用此序號判斷是否具有尚未成功接收的已發報文,如果有的話,該報文會被存放到本地的緩沖區中。等到之前發送的報文全部被接收之後,接收方按照序號對接收的報文依次向上(應用層)遞交,成功遞交的報文會被從緩存區中移除。除了接收到“失序”的報文之外,接收方還有可能接收到重復的報文,因為沒有報文均具有一個唯一的序號,如果該序號小於已經成功遞交或者添加到緩存區中的報文序號,它會被認為是重復接收的報文而被丟棄。
由於每個TCP報文段都具有一個16位的檢驗和(Checksum),所以接收方可以根據它確認數據在傳輸過程中是否被篡改。除此之外,TCP還提供了“流量控制”功能避免了雙方因緩存區大小不一致而導致報文丟失。具體來說,如果發送方的緩沖區大於接收方的緩存區,會導致接收方在緩沖區已滿的情況下無法處理後續接收的報文,所以接收方會將自己緩存區剩余的大小及時通知給發送端,後者據此控制報文發送“流量”。
HTTP(Hypertext Transfer Protocol),全稱為“超文本傳輸協議”,是TCP/IP協議簇的一部分。從圖1-1可以看出,這是一個位於應用層的網絡協議,在它之下的就是TCP協議。由於TCP協議是一個“可靠”的協議,HTTP自然也能提供可靠數據傳輸功能。
IP協議利用IP地址來定位數據報發送的目的地,而利用域名系統(DNS)可以實現域名與IP地址之間的轉換。TCP協議利用端口號標識應用程序,所以某個應用程序在使用TCP協議進行通信的時候必須指定目標應用的IP地址(或者域名)和端口號。HTTP默認采用的端口號為80,而HTTPS(利用TLS/SSL為HTTP提供傳輸安全保障)的默認端口號則為443,當然在網絡可達的前提下,我們可以指定任意的端口。
二、Web資源
這裏所說的資源是一個寬泛的概念,任何寄宿於Web服務器可以利用HTTP協議獲取或者操作的“事物”均可以稱為資源。這也是一個抽象的概念,不僅僅是寄宿於Web服務器的某個靜態物理文件可以視為Web資源,通過Web應用根據請求動態生成的數據也是Web資源。
媒體類型
資源實際上是一種承載著某種信息的數據,相同的信息可以采用不同形態的數據來展現,數據的“形態”主要體現為展示數據所采用的格式,比如一個數據對象可以通過XML格式來表示,也可以通過JSON格式來表示。數據的處理必須依賴於一種已知的格式,所以將Web資源的形態以一種標準化的方式固定下來顯得尤為重要,這就是我們接下來著重介紹的媒體媒體(Media Type)。
不論是通過HTTP請求從Web服務器上獲取資源,還是利用請求向服務器提交資源,響應或者請求的主體(Body)除了包含承載資源本身的數據之外,其報頭(Header)部分還應該包含表示數據形態的媒體類型。
媒體類型又被稱為MIME(Multipurpose Internet Mail Extension)類型,MIME是一個互聯網標準,它擴展了電子郵件標準,使其能夠支持非ASCII字符、二進制格式附件等多種格式的郵件消息。由於MIME在電子郵件系統應用得非常好,所以被HTTP用於描述並標記多媒體內容。下面的列表給出了一種常用的媒體類型。
- text/html:HTML格式的文檔。
- text/xml(application/xml):XML格式的文本。
- text/json(application/json): JSON格式的文本。
- image/gif(image/jpeg、image/png):GIF(JPEG、PNG)格式的圖片。
- audio/mp4(audio/mpeg、audio/vnd.wave):MP4(MPEG、WAVE)格式的音頻文件。
- video/mp4(video/mpeg、video/quicktime):MP4(MPEG、QUICKTIME)格式的視頻文件。
URI、URL和URN
可操作的Web資源應該具有一個 唯一的標識。雖然具有很多唯一性標誌符的種類可供選擇(比如GUID),但是采用URI來標識Web資源已經成為了一種共識,實際上URI的全稱為“統一資源標誌符(Uniform Resource Identifier)”。
我想有很多人弄不清楚URI和URL之間的區別,有人甚至覺得這是同一概念的不同表述而已。一個URL肯定是一個URI,但是一個URI並不一定是一個URL,URL僅僅是URI的一種表現形式而已。兩者的差異其實可以直接從其命名來區分,URI是Web資源的標誌符,所以只要求它具有“標識性”即可;URL全稱為“統一資源定位符(Uniform Resource Locator)”,所以除了標識性之外,它還具有定位的功能,用於描述Web資源所在的位置。
URL不僅僅用於定位目標資源所在的位置,還指名了獲取資源所采用的協議,一個完整的URL包含協議名稱、主機名稱(IP地址或者域名)、端口號、路徑和查詢字符串5個部分。比如對於“ http://www.artech.com:8080/images/photo.png?size=small”這樣一個URL,上述的5個部分分別是“http”、“www.artech.com”、“8080”、“/images/photo.png”和“?size=small”。
除了URL,URN也是URI的一種表現形式,URN全稱“統一資源定位符(Uniform Resource Name)”。URN與資源所在的位置無關,倘若采用URN來唯一標識某個資源,在位置發生改變的時候標誌符依然可以保持不變。URN一般也不會涉及到獲取被標識資源采用的網絡協議,所以不需要為利用不同協議訪問的相同資源定義不同的標誌符。
三、HTTP事務
雖然TCP是一種基於連接的傳輸層協議,並且保存雙方針對同一個連接的多輪消息交換的會話狀態,但是建立其上的HTTP則是一種無狀態的網絡協議。HTTP采用簡單的“請求/響應”消息交換模式,一次HTTP事務(Transaction)始於請求的發送,止於響應的接收。針對客戶端和Web服務器的多次消息交換來說,每個HTTP事務均是相互獨立的。
HTTP方法
HTTP采用簡單的請求/響應模式的消息交換旨在實現針對某個Web資源的某種操作。至於針對資源的操作類型,不外乎CRUD(Create、Retrieve、Update和Delete)而已。一個HTTP請求除了利用URI標誌目標資源之外,還需要通過HTTP方法(HTTP Method或者HTTP Verb)指名針對資源的操作類型。我們常用的HTTP方法 包括GET、POST、PUT、DELETE、HEAD、OPTIONS、TRACE、CONNECTION和PATCH等,我們將在《設計篇》以REST的視角來對它們進行詳細介紹。
響應狀態碼
針對客戶端向Web服務器發送的任意一個HTTP請求,不論在何種情況下得到一個響應,每個響應均具有一個由3位數字表示的狀態碼和相應的描述文字。不同數值的狀態碼體現了不同類型的響應狀態,W3C對響應狀態碼的範圍作了如下的規範。
- 100~199:信息狀態碼,代表請求已被接受,需要繼續處理。
- 200~299:成功狀態碼,代表請求已成功被服務器接收、理解、並接受。
- 300~399:重定向狀態碼,代表需要客戶端采取進一步的操作才能完成請求。
- 400~499:客戶端錯誤狀態碼,代表了客戶端看起來可能發生了錯誤,妨礙了服務器的處理。
- 500~599:服務器錯誤狀態碼,代表了服務器在處理請求的過程中有錯誤或者異常狀態發生,也有可能是服務器意識到以當前的軟硬件資源無法完成對請求的處理。
四、HTTP報文
客戶端和Web服務器在一次HTTP事務中交換的消息被稱為HTTP報頭,客戶端發送給服務器的請求消息被稱為請求報文,服務器返回給客戶端的響應消息被稱為響應報頭。請求報文和響應報頭采用純文本編碼,由一行行簡單的字符串組成。一個完整的HTTP報文由如下三個部分構成。
- 起始行:代表HTTP報文的第一行文字,請求報文利用起始行表示采用的HTTP方法、請求URI和采用的HTTP版本,而響應報文的起始行在承載著HTTP版本和響應狀態碼等信息。
- 報頭集合:HTTP報文的起始行後面可以包含零個或者多個報頭字段。每個報頭表現為一個鍵/值對,鍵和值分別表示報頭名稱和報頭的值,兩者通過冒號(“:”)進行分割。HTTP報文采用一個空行作為報頭集合結束的標誌。
- 主體內容:代表報頭集合結束標誌的空行之後就是HTTP報文的主體部分了。客戶端提交給服務器的數據一般置於請求報頭的主體,而響應報頭的主體也承載著服務器返回給客戶端的數據。不論是請求報文還是響應報文,其主體部分均是可以缺省的。
接下來我們看看一個具體HTTP報文具有怎樣的結構。下面這個文本片段反映的是我們通過Chrome瀏覽器訪問微軟的官網(www.microsoft. com)對應的HTTP請求,起始行體現了HTTP請求的三個基本屬性,即HTTP方法(GET)、目標資源(http://www.microsoft.com/en-us/default.aspx)和協議版本(HTTP/1.1)。
1: GET http://www.microsoft.com/en-us/default.aspx HTTP/1.1
2: Host: www.microsoft.com
3: Connection: keep-alive
4: Cache-Control: max-age=0
5: User-Agent: Mozilla/5.0 (Windows NT 6.1) AppleWebKit/535.7 (KHTML, like Gecko) Chrome/16.0.912.75 Safari/535.7
6: Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
7: Accept-Encoding: gzip,deflate,sdch
8: Accept-Language: en-US,en;q=0.8
9: Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
10: Cookie: ...
上述這個請求報文不具有主體,所以起始行之外的所有內容均為報頭集合,我們們可以根據這些報頭獲得主機名稱、采用的緩存策略、瀏覽器相關信息、以及客戶端支持的媒體類型(Media Type)、編碼方式、語言和字符集等。
前面的HTTP請求通過瀏覽器發送給服務端之後會接收到具有如下結構的響應報文,我們可以此從它的起始行得到采用的HTTP版本(HTTP/1.1)和響應狀態碼(“200 OK”,表示請求被正常接收處理)。響應的內容被封裝到響應報文的主體部分,其媒體類型的通過報頭“Content-Type”表示。由於該響應報文的主體內容是一個HTML文檔,所以“Content-Type”報頭表示的媒體類型為“text/html”。
1: HTTP/1.1 200 OK
2: Cache-Control: no-cache
3: Pragma: no-cache
4: Content-Type: text/html; charset=utf-8
5: Content-Encoding: gzip
6: Expires: -1
7: Vary: Accept-Encoding
8: Server: Microsoft-IIS/7.5
9: X-AspNet-Version: 2.0.50727
10: VTag: 791897542300000000
11: P3P: CP="ALL IND DSP COR ADM CONo CUR CUSo IVAo IVDo PSA PSD TAI TELo OUR SAMo CNT COM INT NAV ONL PHY PRE PUR UNI"
12: X-Powered-By: ASP.NET
13: Date: Wed, 18 Jan 2012 07:06:25 GMT
14: Content-Length: 34237
15:
16: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
17: <html>…</html>
[1]超文本/超媒體(HyperText/HyperMedia):超文本是一份呈現文本內容的電子文檔,其核心在於可以利用內嵌的“超鏈接(Hyperlink)”直接訪問引用的另一份文檔。超媒體對超文本作了簡單的擴展以呈現多媒體內容(比如圖片、音頻和視頻等)。HTML文檔是我們常見的最為典型的超文本/超媒體文件。
[2] 除了采用這種4個層次的劃分方法之外,還具有另外兩種典型的劃分方式。其中一種在鏈路層下面添加一個基於物理網絡硬件的物理層,這種劃分方法與此沒有本質的區別。另外一種則是將TCP/IP協議簇劃分為包括應用層、表示層、會話層、傳輸層、網絡層、鏈路層和物理層在內的7個層次。
參考資料:
[1] 《HTTP: The Definitive Guide》, By By David Gourley, Brian Totty, Marjorie Sayer, Anshu Aggarwal, Sailu Reddy
[2] 《RESTful Web Services》, RESTful Web Services
[3] 《A Brief Introduction to REST》,http://www.infoq.com/articles/rest-introduction
[4] 《TCP/IP Illustrated (Volumn 1: The Protocol)》, by W. Richard Stevens
原文鏈接:http://www.cnblogs.com/artech/p/restful-web-api-01.html
我所理解的RESTful Web API [Web標準篇]