1. 程式人生 > >HTTP網路請求原理 (二) Http報文格式解析

HTTP網路請求原理 (二) Http報文格式解析

請求報文

不同的請求方式,它們的請求格式可能是不一樣的,請求格式就是我們所說的報文格式. 但是,通常來說一個HTTP請求報文由請求行(request line),請求頭部(head),空行和請求資料4個部分組成,下圖給出了請求報文的一般格式.
這裡寫圖片描述

  1. 起始行
    報文的第一行就是起始行,在請求報文中用來說明要以什麼方式做什麼請求,而在響應報文中粗略說明了報文的執行結果.
  2. 首部欄位
    起始行後面有零個或多個首部欄位. 每個首部欄位都包含一個名字和一個值,為了便於解析,兩者之間用冒號(如Connection: keep-Alive)來分隔. 首部以一個空行結束. 新增一個首部欄位和新增新行一樣簡單.
  3. 主體
    首部欄位的空行之後就是可選的報文主體了,其中包含了所有型別的資料. 請求主體中包括了要傳送給Web伺服器的資料; 響應主體中裝載了要返回給客戶端的資料. 起始行和首部都是結構化的文字形式,而主體則可以包含任意的二進位制資料(如圖片,視訊,音軌,軟體程式). 當然,主體中也可以包含文字.

下面我們就來學習常用的GET,POST,PUT,DELETE四種請求方式的報文格式.

我們首先學習比較簡單的GET和DELETE請求方式,對於DELETE和GET來說,由於它們的功能是刪除和獲取,因此,只要將URL構造為要處理的資源即可. 也就是說它們所有的引數附加在資源URL的最後,第一個引數前通過”?”符號連線,然後請求引數按照”引數名=引數值”的形式進行追加,每個引數之間用”&”連線. 例如

http://www.myhost.com/image?id=123&fotmat=png ,該URL的引數有id和format,它們的值分別為123和png,如果該請求是DELETE,那麼將刪除 http://www.myhost.com/image 下id為123,格式為png的圖片,如果是GET,那麼則是獲取該圖片. 需要注意的是,GET和DELETE的URL最大長度為1024位元組,也就是1KB.

在瀏覽器中輸入 http://www.devtf.cn/?p=909 ,這是開發技術前線第十九期週報的URL,得到的請求報文如下所示:

GET /?p=909 HTTP/1.1
Host: www.devtf.cn
Cache-Control: no-cache

根據上述的HTTP請求格式可知,第一行為請求行,代表請求方式是GET,子路徑為/?p=909,也是表示引數p的值為909,HTTP版本為1.1 , 後兩行是請求的HEADER區域,第一個請求頭是主機地址,值www.devtf.cn. 另外還有一個Cache-Control的請求頭,值為no-cache. GET,DELETE請求的所有引數都附加在URL連結中,因此,請求資料部分為空.

對於PUT和POST來說,他們的報文格式一般是表單形式,也就是說這兩個請求方式的引數儲存在報文的請求資料(報文主體)的位置上:

POST /api/feed/ HTTP/1.1
Accept-Encoding: gzip
Content-Length: 225873
Content-Type: multipart/form-data; boundary=OCqxMF6-JxtxoMDHmoG5W5eY9MGRsTBp
Host: www.myhost.com
Connection: Keep-Alive

--OCqxMF6-JxtxoMDHmoG5W5eY9MGRsTBp
Content-Disposition: form-data; name="username"
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Mr.Simple
--OCqxMF6-JxtxoMDHmoG5W5eY9MGRsTBp
Content-Disposition: form-data; name="images";
filename="/storage/emulated/0/Camera/jdimage/1xh0e3yyfmpr2e35tdowbavrx.jpg"
Content-Type: application/octet-stream
Content-Transfer-Encoding: binary

這裡是圖片的二進位制資料,資料太長,在此省略
--OCqxMF6-JxtxoMDHmoG5W5eY9MGRsTBp--

上述請求的含義為向 www.myhost.com/api/feed/ 這個地址傳送一個POST請求. 這個請求的資料格式(Content-Type)為multipart/form-data,報文的boundary值為OCqxMF6-JxtxoMDHmoG5W5eY9MGRsTBp. 該報文有兩個引數,一個引數是文字型別的username引數,值為Mr.Simple,另一個是名為images的二進位制引數,資料是一張圖片的二進位制資料,這裡我們將圖片的二進位制資料省略了.

需要注意的是,一個引數是以兩個橫槓加上boundary開始的,然後是該引數的一些屬性資訊,例如引數名,格式等,然後加上一個空行,最後才是引數的值. 例如上述的username引數,完整的格式為:

--OCqxMF6-JxtxoMDHmoG5W5eY9MGRsTBp                          // 兩個橫槓加上boundary值
Content-Disposition: form-data; name="username"                 //這3個是請求引數的Header屬性
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
                                                                        //這裡是一個不可省略的空行
Mr.Simple                                                               //這是引數值

POST與PUT都必須遵循這種的格式,每個引數以兩個橫槓和boundary分隔,引數header與引數值之間有一個空行. 另一個要注意的地方是,請求資料的最後是兩個橫槓+boundary值+兩個橫槓作為整個報文的結束符. 當手動構建POST請求報文時,這些格式就尤為重要,如果格式不正確,那麼服務端將無法正確解析你的請求.

響應報文

HTTP響應也由3個部分組成,分別是:狀態行,訊息報頭,響應正文. 如下所示,HTTP響應的格式與請求的格式十分類似:

<狀態行>
<響應報文header>
<空行>
[響應報文內容]

正如你所見,在響應中唯一真正的區別在於第一行中用狀態資訊代替了請求資訊. 狀態行(status line)通過提供一個狀態碼來說明所請求的資源情況.

狀態行格式如下:

HTTP-Version Status-Code Reason-Phrase CRLF

其中,HTTP-Version表示伺服器HTTP協議的版本; Status-Code表示伺服器發回的響應狀態程式碼; Reason-Phrase表示狀態程式碼的文字描述. 狀態程式碼由3位數字組成,第一個數字定義了響應的類別,且有5種可能取值,如下表所示.

取值範圍 含義
100~199 指示資訊: 表示請求已接受,繼續處理
200~299 請求成功: 表示請求已被成功接收,理解,接收
300~399 重定向: 要完成請求必須進行更進一步的操作
400~499 客戶端錯誤: 請求有語法錯誤或請求無法實現
500~599 伺服器端錯誤: 伺服器未能實現合法的請求

常見狀態程式碼,狀態描述的說明如下.

  • 200 OK: 客戶端請求成功.
  • 400 Bad Request: 客戶端請求有語法錯誤,不能被伺服器所理解.
  • 401 Unauthorized: 請求未經授權,這個狀態程式碼必須和WWW-Authenticate報頭域一起使用.
  • 403 Forbidden: 伺服器收到請求,但是拒絕提供服務.
  • 404 Not Found: 請求資源不存在,舉個例子: 輸入了錯誤的URL.
  • 500 Internal Server Error: 伺服器發生不可預期的錯誤.
  • 503 Server Unavailable: 伺服器當前不能處理客戶端的請求,一段時間後可能恢復正常,舉個例子: HTTP/1.1 200 OK (CRLF).

例如,這是一個GET請求的Response返回示例:

HTTP/1.1 200 OK
Date: Sat, 31 Dec 2005 23:59:59 GMT
Content-Type: text/html;charset=
Content-Length: 122

<html>
    <head>
        <title>開發技術前線<title>
    </head>
    <body>
        <!-這裡是Body -->
    <body>
</html>

該請求返回碼為200,表示請求成功. 返回的資料型別為text/html,編碼為ISO-8859-1,內容長度為122. 在一個空行之後就是返回的資料, 也就是一個html頁面,也就是一個html頁面. 客戶端接受到這個返回結果之後,直接將結果展示到WebView上即可. 如果返回的是Json,XML格式的資料,那麼,我們通常需要解析這些資料,並且將根據結果進行其他相應的處理.

常見的請求頭部

請求頭部由鍵值對組成,每行一對,關鍵字和值用英文冒號”:”分隔. HTTP規範定義了幾種首部欄位,應用程式也可以隨意發明自己所用的首部. HTTP收不可以分為以下幾類,如下表所示.

首部型別 作用
通用首部 既可以出現在請求報文中,也可以出現在響應報文中
請求首部 提供更多有關請求的資訊
響應首部 提供更多有關響應的資訊
實體首部 描述主體的長度和內容,或者資源自身
擴充套件首部 HTTP規範中沒有定義的新首部

請求頭部通知伺服器關於客戶端請求的資訊,典型的請求頭有:

  • Content-Type: 請求資料的格式.
  • Content-Length: 訊息長度.
  • Host: 請求的主機名,允許多個域名同處一個IP地址,即虛擬主機.
  • User-Agent: 發出請求的瀏覽器型別,可以自行設定.
  • Accept: 客戶端可識別的內容型別列表.
  • Accept-Encoding: 客戶端可識別的資料編碼.
  • Connection: 允許客戶端和伺服器指定與請求/響應連線與有關的選項,例如:設定為Keep-Alive則表示保持連線.
  • Transfer-Encoding: 告知接收端為了保證報文的可靠傳輸,對報文采用了什麼編碼方式.