http協議進階(三)http報文


一、報文流

http報文是在http應用程序之間發送的數據塊(也可稱為數據包)、這些數據塊以一些文本的元信息(meta-information)開頭,描述了報文的內容及含義,后面跟着

可選的數據部分,這些報文在客戶端、服務器和代理之間流動;常說的術語“流入”、“流出”、“上游”、“下游”就是描述報文方向的

 

1、報文流入源服務器

http使用術語流入(inbound)和流出(outbound)來描述事務處理的方向;報文流入源服務器,工作完成后,流回用戶的Agent代理中,如下圖

 

2、報文向下游流動

不管是請求還是響應報文,所有報文都會向下游流動,所有報文發送者都在接收者的上游,如下圖

 

二、報文的組成

http報文是簡單的格式化數據塊,如下圖

每條報文包含一個客戶端請求或者服務端響應,由三部分組成:1)對報文進行描述的起始行;2)包含屬性的首部(header)模塊;3)可選的,包含數據的主體(body)部分

起始行和首部就是由行分隔的 ASCII文本。每行都以一個由2個字符組成的行終止序列作為結束,包括一個回車符(ASCII碼13)和一個換行符(ASCII碼10),這個行終止

序列可以寫為CRLF。(穩健的應用程序也應該接受單個換行符作為行的終止)

實體或報文的主體是一個可選數據塊,與起始行和首部不同的是,主體中可包含文本或二進制數據,也可以為空

如上圖,Content-type行說明了主體是一個純文本文檔,Content-length說明了主體有19字節

 

1、報文的語法

所有的http報文都分為請求報文響應報文,請求報文會向服務器發送一個請求動作,響應報文會將請求結果返回給客戶端,其結構基本相同;下圖顯示了獲取一張GIF圖所需的請求和響應報文

這是請求報文的格式                                             這是響應報文的格式

<method> <request-URL> <version>                            <method> <status> <version>

<headers>                                                   <heraers> 

<entity-body>                                               <entity-body>

下面是對各部分的簡述:

方法(method):客戶端希望服務器對資源執行的動作,是一個單獨的詞,比如GET、HEAD、POST等

之前的博客http://www.cnblogs.com/imyalost/p/5630940.html中有簡單介紹幾種方法,不過后面會詳細解釋這些方法

請求URL(request-URL):命名了請求資源,或者URL路徑組件的完整URL;如果直接與服務器進行對話,只要URL的路徑是決定路徑,通常不會出現問題(上一篇隨筆有詳細介紹URL......)

版本(version):報文所使用的http協議版本——HTTP/<major>.<minor>;其中主要版本號(major)和次要版本號(minor)都是整數,本篇后面詳解

狀態碼(status-code):3位數字,描述請求過程中發生的情況,每個狀態碼第一位描述狀態的一般類別(成功/錯誤),本篇后面解釋http規范的狀態碼及其含義

之前的博客http://www.cnblogs.com/imyalost/p/5688169.html也有簡單介紹

狀態碼還有一種可讀版本,包含終止序列之前的版本;比如HTTP/1.1 200 NOT OK和HTTP/1.1 200 OK中原因短語不同,但同樣被當做成功指示處理

首部(header):可以有0個或多個首部,每個首部包含一個名字,后面跟一個冒號,然后一個可選空格,接着一個值,最后是CRLF。首部由一個空行(CRLF)結束,表示首部列表的結束和實體主體的開始。

實體主體(entity-body):包含一個由任意數據組成的數據塊。

 

2、起始行

所有http報文都以一個起始行作為開始;請求報文說明了要做什么,響應報文說明發生了什么

2.1 請求行

請求報文請求服務器對資源進行一些操作。請求報文起始行,稱為請求行,包含一個方法和一個請求。

該方法描述了服務器應該執行哪些操作,請求URL描述了要對哪個資源執行這個方法,請求行中還包括http版本,告知服務器,客戶端使用哪個版本http協議,由空格符分隔

上圖中,請求方法為GET,請求URL為test/hi-there.txt,http版本為1.1。

 

2.2 響應行

響應報文承載了狀態信息和操作產生的所有結果數據,將其返回給客戶端。響應報文起始行,稱為響應行,包含了使用的http版本,數字狀態碼,以及描述操作狀態或文本形式的原因短語。

這些字段由空格符進行分隔,在上圖中,http版本為1.0,狀態碼200(表示成功),原因短語為OK,表示文檔被成功返回。

 

2.3 方法

請求的起始行以方法作為開始,方法用來告知服務器做什么。如上圖,方法就是GET,下表列出一些現版本http有的一些方法

具體的方法介紹下面會介紹

 

2.4 狀態碼

狀態碼用來告訴客戶端,發生了什么事;狀態碼位於響應的起始行中。狀態碼在每條響應報文的起始行中返回的,以一個數字和一個可讀的狀態組成;數字碼便於程序進行差錯處理,原因短語則便於理解

下面列出狀態碼的分類:

具體的方法介紹下面會介紹

 

2.5 原因短語

原因短語為狀態碼提供了文本形式的解釋,和狀態碼成對出現,是狀態碼的可讀版本,應用程序將其傳給客戶,說明在請求期間發生了什么;稍后會整理出一些狀態碼和其建議使用的一些原因短語

 

2.6 版本號

版本號會以http/x、y的形式出現在請求和響應報文的起始行中,為應用程序提供了一種將自己遵循的協議版本告知對方的方式

通信時最好使請求和響應的版本號保持一致,否則很容易造成誤解,使程序無法識別

PS:版本號不會被當做分數處理,每個數字都是獨立的,比如,HTTP/2.22版本高於HTTP/2.3

 

3、首部

http首部字段向請求和響應報文中添加一些附加信息;本質來講,他們知識一些名/值對的列表。

 

3.1 首部分類

通用首部:即可出現在請求報文中,也可出現在響應報文中

請求首部:提供更多有關請求的信息

響應首部:提供更多有關響應的信息

實體首部:描述主體的長度和內容,或者資源本身

擴展首部:規范中沒有定義的新首部

每個http首部都有一種簡單的語法:名字后面是冒號(:),然后跟上可選的空格,再跟上字段值,最后以一個CRLF結束

 

3.2 首部延續行

將長的首部行分為多行可提高可讀性,每行前面至少有一個空格或制表符(tab),例如

HTTP/1.1 200 OK

Conteng-Type: image/gif

Content-Length: 8572

Server: Test Server

Version 1.0

上面的例子,響應報文中包含一個Server首部,其值被划分為多個延續行,該首部完整值為Server: Test Server Version 1.0

 

4、實體的主體部分

http報文的第三部分為可選的實體主體部分,實體是主體的http報文的負荷,就是http要傳輸的內容,資源

http報文可承載很多類型的數字數據:圖片、視頻、HTML文檔、軟件應用程序、電子郵件等

 

三、方法

1、GET

GET是最常用的方法,通常用於請求服務器發送某個資源(資源是已被服務器識別或標識的)給客戶端; 如下圖

服務器在獲取GET請求參數時用Request.QueryString,意思為獲取地址欄中的參數,就是“?”后面的參數,如果是多個,就用&連起來

 

2、HEAD

HEAD和GET方法類似,但在響應中只返回首部,不返回實體的主體部分。使用HEAD方法,可以

*在不獲取資源的情況下了解資源的實際情況(資源類型)

*通過查看狀態碼,確認資源是否存在(有效性)

*通過查看首部,測試資源是否被修改(如修改,資源修改時間等)

 

3、PUT

與GET相反,PUT方法會向服務器寫入文檔(有些系統會允許用戶創建web界面,並用PUT方法直接將其安裝到web服務器上)

PUT方法實際上就是讓服務器用請求中包含的主體部分來創建一個由請求的URL命名的新文檔;或者URL已存在的話,就用這個主體來替代它。

因為PUT允許用戶對內容進行修改,所以現在很少用這個方法,如果使用了這個方法,都要求用戶使用授權的密碼登陸(后面會整理出來關於安全認證的相關內容)

 

4、POST

POST方法用來向服務器發送提交數據的請求,具體的內容這里就不贅述了,之前有寫過關於這方面的隨筆,里面介紹了post及它與get的區別等內容(http://www.cnblogs.com/imyalost/p/5630940.html

 

5、TRACE

客戶端發起一個請求時,請求可能要穿過防火牆、代理、網關或者其他應用程序,每個中間節點可能都會修改原始的http請求,TRACE允許客戶端在最終把請求發給服務器時,查看它最終的樣子

TRACE請求會在目的服務器端發起一個“回環”診斷。最后一站服務器會彈回一個TEACE響應,並在響應報文主體中攜帶原始請求報文,這樣客戶端就可以查看在所有中間節點上,原始報文是否被修改或毀壞

 

6、OPTIONS

請求web服務器告知其支持的各種功能;可以詢問服務器支持哪些方法,或者對某些特殊資源支持哪些方法(有些服務器可能只支持對一些特殊類型的對象使用特定操作)

為客戶端提供了一種手段:不用實際訪問資源就可判定訪問各種資源的最優方式

 

7、DELETE

請求服務器刪除請求URL所指定的資源;但客戶端應用程序不一定會執行刪除操作,因為http協議規范允許服務器在不通知客戶端的情況下撤銷請求。如下圖

 

8、擴展方法

http被設計成可擴展的,這樣新特性就不會使老的版本失效。擴展方法指的是沒在HTTP/1.1中規范定義的,服務器為它管理的資源實現一些HTTP服務,為開發者提供了一種擴展這些HTTP服務能力的手段

下表列出了一些常用的擴展方法:

上面例子中的方法便於用過http將web內容發布到web服務器上

不是所有的擴展都是在正式規范中定義的,因此,擴展方法秉持“對發送內容要求嚴格,對所接受的內容寬容點”來處理一般的HTTP擴展方法很重要

 

四、狀態碼

響應報文的返回狀態碼分為五類,之前的隨筆進行了介紹,這里就當做是補充吧

狀態碼是一種理解事務處理結果的便捷方式;下面列出一些常見的原因短語例子,都是目前最常用的HTTP/1.1規范推薦使用的

1、100~199——信息性狀態碼

100 Continue的目的是對這樣的情況進行優化:http客戶端應用程序有一個主體的實體部分要發送給服務器,但發送之前希望查看服務器是否會接受這個實體

 

1.1 客戶端與100 Continue

如果客戶端向服務器發送一個實體,並願意在發送前等待100 Continue響應,那么客戶端就要發送一個攜帶了值為100 Continue的EXpect請求首部;如果客戶端沒發送實體,

就不應發送100 Continue Expect首部。因此客戶端只有在避免向服務器發送一個服務器無法處理或使用的較大的實體時,才應使用100 Continue

解決辦法:發送了100 Continue的Expect首部值的客戶端不應一直等待響應,超過一定時間(可設置),自動將實體發送出去;同時做好應對非預期100 Continue響應的准備

 

1.2 服務器與100 Continue

如果服務器收到帶有值為100 Continue的Expect首部請求,它會用100 Continue或一條錯誤碼來響應;服務器永遠不應向沒有發送100 Continue請求的客戶端發送100 Continue狀態碼

如果服務器在發送100 Continue響應前收到部分或全部實體,說明客戶端決定繼續發送數據,此時,服務器不需要發送這個狀態碼,但讀完請求,應繼續返回一個最終狀態碼(跳過100 Continue狀態)

如果服務器收到帶有100 Continue的請求,且它決定在讀完實體主體前結束請求,就不應僅僅發送一條響應並關閉連接,這樣會影響客戶端接收響應

 

1.3 代理與100 Continue

代理從客戶端收到帶有100 Continue期望的請求,有以下幾種情況:

如果知道下游服務器是http/1.1兼容或不清楚下游服務器與哪一個版本兼容,應將Expect首部放在請求中向下轉發

如果知道下游服務器只能與http/1.1以下的版本兼容,就應該以417 Expectation Failed錯誤進行響應

如果代理決定代表與http/1.1或之前的版本兼容的客戶端,在其請求中放入Expect首部和100 Continue值,那么它不應將100 Continue轉發給客戶端

 

2、200~299——成功狀態碼

下面列車一些服務器用來表示成功的狀態碼,分別對應不同的請求

 

3、300~399——重定向狀態碼

告知客戶端使用替代位置來訪問它感興趣的資源;或提供一個替代的響應而不是資源內容

或在資源已被移動情況下,發送一個重定向狀態碼和一個可選的Location首部告知客戶端,資源已被移動,且在哪里可以找到尋找的資源,如下圖:將請求重定向到新的位置

可通過某些重定向狀態碼對資源的應用程序本地副本與源服務器上的資源進行驗證;比如http應用程序可以查看本地資源是否是最新的或者是否被修改過

總之,對那些包含了重定向狀態碼的非HEAD請求進行響應時,最好包含一個實體,其實體中包含描述信息和指向(多個)重定向URL的鏈接——如上圖第一個響應報文

下表列出已定義的重定向狀態碼:

上面302、303於307狀態碼之間存在一些交叉,區別在於HTTP/1.0和HTTP/1.1對其的處理方式:

HTTP/1.0發起一個POST請求,並在響應中收到302重定向狀態碼時,它會接受Location首部重定向的URL,並向那個URL發起一個GET請求

如果HTTP/1.0服務器收到來自HTTP/1.0客戶端的POST請求之后,發出302狀態碼,服務器希望客戶端能接受重定向URL並向重定向URL發一個GET請求

但是,HTTP/1.1規范使用303狀態碼來實現以上行為(服務器發送303狀態碼重定向客戶端的POST請求,在其后面跟上一個GET請求)

為規避上述問題,HTTP/1.1規范:對於HTTP/1.1客戶端,用307來取代302狀態碼進行重定向(保存302狀態碼,留待HTTP/1.0使用→→服務器遇到類似情況需要先檢查客戶端HTTP版本)

 

4、400~499——客戶端錯誤狀態碼

有時候客戶端會發送一些服務器無法處理的請求,比如格式錯誤的報文或者不存在的URL,服務器會返回給我狀態碼告訴我們它的反應

很多客戶端錯誤都由瀏覽器處理,只有少量錯誤,比如404,會被用戶看到;下表列出各種客戶端錯誤狀態碼

 

5、500~599服務器錯誤狀態碼

有時客戶端發起一個請求,但服務器由於本身缺陷或子元素出錯時,會出現此類問題,服務器返回5XX代碼來描述遇到的問題

下表列出一些已定義的服務器錯誤狀態碼

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM