HTTP之實體和編碼

1. Content-Length: 實體的大小

Content-Length 首部指示出報文中實體主體的字節大小。這個大小是包含了全部內容編碼的,好比,對文本文件進行了 gzip 壓縮的話,Content-Length 首部就是壓縮後的大小,而不是原始大小。html

除非了使用了分塊編碼,不然 Content-Length 首部就是帶有實體主體的報文必須使用的。使用 Content-Length 首部是爲了可以檢測出服務器崩潰而致使的報文截尾,並對共享持久鏈接的多個報文進行正確分段。算法

1.1 檢測截尾

客戶端經過 Content-Length 來檢測報文截尾。緩存

緩存代理服務器一般不會爲沒有顯式 Content-Length 首部的 HTTP 主體作緩存,以此來減少緩存已截尾報文的風險。服務器

1.2 Content-Length 與持久鏈接

若是響應經過持久鏈接傳送,就可能有另外一條 HTTP 響應緊隨其後。客戶端經過 Content-Length 首部就能夠知道報文在何處結束,下一條報文從何處開始。由於鏈接是持久的,客戶端沒法依賴鏈接關閉來判別報文的結束。網絡

有一種狀況下,使用持久鏈接時能夠沒有 Content-Length 首部,即採用分塊編碼(chunked encoding)時。在分塊編碼的狀況下,數據是分爲一系列的塊來發送的,每塊都有大小說明。併發

1.3 內容編碼

若是主體進行了內容編碼,Content-Length 首部說明的就是編碼後(encoded)的主體的字節長度,而不是未編碼的原始主體的長度。app

2. 實體摘要

服務器使用 Content-MD5 首部發送對實體主體運行 MD5 算法的結果。只有產生響應的原始服務器能夠計算併發送 Content-MD5 首部。中間代理和緩存不該當修改或添加這個首部,不然就會與驗證端到端完整性的這個最終目的相沖突。Content-MD5 首部是在對內容作了全部須要的內容編碼以後,尚未作任何傳輸編碼以前,計算出來的。爲了驗證報文的完整性,客戶端必須先進行傳輸編碼的解碼,而後計算所獲得的未進行傳輸編碼的實體主體的 MD5。ide

倘若一份文檔使用 gzip 算法進行壓縮,而後用分塊編碼發送,那麼就對整個經 gzip 壓縮的主體進行 MD5 計算。性能

3. 媒體類型和字符集

Content-Type 首部字段說明了實體主體的 MIME 類型。MIME 類型是標準化的名字,用以說明做爲貨物運載實體的基本媒體類型。優化

MIME 類型由一個主媒體類型(好比:text、image 或 audio 等)後面緊跟一條斜線以及一個子類型組成,子類型用於進一步描述媒體類型。

下列是一些 Content-Type 首部中經常使用的 MIME 類型。

  • text/html:實體主體是 HTML 文檔
  • text/plain:實體主體是純文本文檔
  • image/gif:實體主體是 GIF 格式的圖像
  • image/jpeg:實體主體是 JPEG 格式的圖像
  • audio/x-wav:實體主體包含 WAV 格式的圖像
  • model/vrml:實體主體是三維的 VRML 模型
  • application/vnd.ms-powerpoint:實體主體是 Microsoft PowerPoint 演示文檔
  • multipart/byterange:實體主體有若干部分,每一個部分都包含了完整文檔中不一樣的字節範圍
  • message/http:實體主體包含完整的 HTTTP 報文

Content-Type 首部說明的是原始實體主體的媒體類型。例如,若是實體通過內容編碼的話,Content-Type 首部說明的還是編碼以前的實體主體的類型。

3.1 文本的字符編碼

Content-Type 首部還支持可選的參數來進一步說明內容的類型。如 charset(字符集)參數,它說明把實體中的比特轉換爲文本文件中的字符的方法:

Content-Type: text/html; charset=iso-8859-4

3.2 多部分媒體類型

MIME 中的 multipart(多部分)電子郵件報文中包含多個報文,它們合在一塊兒做爲單一的複雜報文發送。每一部分都是獨立的,有各自的描述其內容的集;不一樣的部分之間用分界字符串鏈接在一塊兒。

HTTP 也支持多部分主體。不過,一般只用在下列兩種情形之一:提交填寫好的表格,或是做爲承載若干文檔片斷的範圍響應。

3.3 多部分表格提交

當提交填寫的 HTTP 表格時,變長的文本字段和上傳的對象都做爲多部分主體裏面獨立的部分發送,這樣表格中就能夠填寫各類不一樣類型和長度的值。

HTTP 使用 Content-Type: multipart/form-data 或 Content-Type: multipart/mixed 這樣的首部以及多部分主體來發送這種請求,示例以下:

Content-Type: multipart/form-data; boundary=[abcdefghijklnopqrstuvwxyz]

其中 boundary 參數說明了分割主體中不一樣部分所用的字符串。

下例展現了 multipart/form-data 編碼。假設有以下表格:

若用戶在文本輸入字段中鍵入了 Sally,並選擇了文本文件 essayfile.txt,用戶 Agent 代理可能會發回下面這樣的數據:

Contet-Type: multipart/form-data; boundary=AaB03x
--AaB03x
Content-Disposition: form-data; name="submit-name"
Sally
--AaB03x
Content-Disposition: form-data; name="files"; filename="essayfile.txt"
Content-Type: text/plain
..contents of essayfile.txt
--AaB03x

3.4 多部分範圍響應

HTTP 對範圍請求的響應也能夠是多部分的。這樣的響應中有 Content-Type: multipart/byteranges 首部和帶有不一樣範圍的多部分主體。以下示例展現了對文檔不一樣範圍的請求產生的響應:

4. 內容編碼

HTTP 應用程序有時在發送以前須要對內容進行編碼。

4.1 內容編碼過程

  1. 網站服務器生成原始響應報文,其中有原始的 Content-Type 和 Content-Length 首部。
  2. 內容編碼服務器建立編碼後的報文。編碼後的報文有一樣的 Content-Type 但 Content-Length 可能不一樣(如主體被壓縮了)。內容編碼服務器在編碼後的報文中增長了 Content-Encoding 首部,這樣接收的應用程序就能夠進行解碼了。
  3. 接收程序獲得編碼後的報文,進行解碼,得到原始報文。

4.2 內容編碼類型

HTTP 定義了一些標準的內容編碼類型,並容許用擴展編碼的形式增添更多的編碼。由互聯網號碼分配機構(IANA)對各類編碼進行標準化,它給每一個內容編碼算法分配了惟一的代號。Content-Encoding 首部就用這些標準化的代號來講明編碼時使用的算法。

  • gzip:代表實體採用 GNU zip 編碼
  • compress:代表實體採用 Unix 的文件壓縮程序
  • deflate:代表實體是用 zlib 的格式壓縮的
  • identity:代表沒有對實體進行編碼。當沒有 Content-Encoding 首部時,就默認爲這種狀況

gzip、compress 以及 deflate 編碼都是無損壓縮算法,用於減小傳輸報文的大小,不會致使信息損失。

4.3 Accept-Encoding 首部

Accept-Encoding 字段包含了用逗號分隔的支持編碼的列表:

  • Accept-Encoding: compress, gzip
  • Accept-Encoding:
  • Accept-Encoding: *
  • Accept-Encoding: compress;1=0.5, gzip;q=1.0
  • Accept-Encoding: gzip;q=1.0, identity; q=1.0, *;q=0

客戶端能夠給每種編碼附帶 Q(質量)值參數來講明編碼的優先級。Q 值的範圍從 0.0 到 1.0,0.0 說明客戶端不想接受所說明的編碼,1.0 則代表最但願使用的編碼。"*" 表示 "任何其餘方法"。

identity 編碼代號只能在 Accept-Encoding 首部中出現,客戶端用它來講明相對於其餘內容編碼算法的優先級。

5. 傳輸編碼和分塊編碼

使用傳輸編碼是爲了改變報文中的數據在網絡上傳輸的方式。

5.1 Transfer-Encoding 首部

HTTP 協議中只定義了下面兩個首部來描述和控制傳輸編碼:

  • Transfer-Encoding:告知接收方爲了可靠地傳輸報文,已經對其進行了何種編碼。
  • TE:用在請求首部中,告知服務器可使用哪些傳輸編碼擴展。

以下示例,請求使用了 TE 首部來告訴服務器它能夠接受分塊編碼而且願意接受附在分塊編碼的報文結尾上的拖鞋:

GET /new_products.html HTTP/1.1
Host: www.joes-hardware.com
User-Agent: Mozilla/4.61 [en] (WinNT; I)
TE: trailers, chunked
...

對它的響應中包含 Transfer-Encoding 首部,用該告訴接收方已經用分塊編碼對報文進行了傳輸編碼:

HTTP/1.1 200 OK
Transfer-Encoding: chunked
Server: Apache/3.0
...

5.2 分塊編碼

分塊編碼把報文分割爲若干個大小已知的塊。塊之間是緊挨着發送的,這樣就不須要在發送以前知道整個報文的大小了。

注:分塊編碼是一種傳輸編碼,所以是報文的屬性,而不是主體的屬性。多部分編碼就是主體的屬性,它和分塊編碼是徹底獨立的。

1. 分塊與持久鏈接

當使用持久鏈接時,在服務器寫主體以前,必須知道它的大小並在 Content-Length 首部中發送。若是服務器動態建立內容,就可能在發送以前沒法知道主體的長度。

分塊編碼解決了這種問題,只要容許服務器把主體逐塊發送,說明每塊的大小就能夠了。

分塊編碼由起始的 HTTP 響應首部塊開始,隨後是一系列分塊。每一個分塊包含一個長度值和該分塊的數據。長度值是十六進制形式並將 CRLF 與數據分隔開。分塊中數據的大小以字節計算,不包括長度值與數據之間的 CRLF 序列以及分塊結尾的 CRLF 序列。最後一個塊的長度值爲 0,表示"主體結束"。

2. 分塊報文的拖掛

若客戶端的 TE 首部中說明它能夠接受拖掛的話,就能夠在分塊的報文最後加上拖掛。產生原始響應的服務器也能夠在分塊的報文最後加上拖掛。拖掛的內容是可選的元數據,客戶端不必定須要理解和使用(客戶端能夠忽略並丟棄拖掛中的內容)。

拖掛中能夠包含附帶的首部字段,它們的值在報文開始的時候多是沒法肯定的(如,必需要先生成主體的內容)。Content-MD5 首部就是一個能夠在拖掛中發送的首部,由於在文檔生成以前,很難算出它的 MD5。

除了 Transfer-Encoding、Trailer 以及 Content-Length 首部以外,其餘 HTTP 首部均可以做爲拖掛發送。

6. 範圍請求

HTTP 容許客戶端只請求文檔的一部分,或者說某個範圍。服務器能夠經過在響應中包含 Accept-Rranges 首部的形式向客戶端說明能夠接受的範圍請求。這個首部的值是計算範圍的單位,一般是以字節計算的:

HTTP/1.1 200 OK
Date: Fri, 05 Nov 1999 22:35:15 GMT
Server: Apache/1.2.4
Accept-Ranges: bytes
...

7. 差別編碼

差別編碼是 HTTP 協議的一個擴展,它經過交換對象改變的部分而不是完整的對象來優化傳輸性能。

客戶端在 If-None-Match 首部中使用的是它所持有頁面版本的惟一標識,這個標識是服務器以前響應客戶端時在 ETag 首部中發送的。

差別編碼所用的首部:

  • ETag:文檔每一個實例的惟一標識符。由服務器在響應中發送;客戶端在後繼請求的 If-Match 首部和 If-None-Match 首部中可使用它
  • If-None-Match:客戶端發送的請求首部,當且僅當客戶端的文檔版本與服務器不一樣時,才行服務器請求該文檔
  • A-IM:客戶端請求首部,說明能夠接受的實例操控類型
  • IM:服務器響應首部,說明做用在響應上的實例操控的類型。當響應代碼是 226 IM Used 時,會發送這個首部
  • Delta-Base:服務器響應首部,說明用於計算差別的基線文檔的 ETag 值(應當與客戶端請求中的 If-None-Match 首部裏的 ETag 相同)

7.1 實例操控、差別生成器和差別應用器

客戶端可使用 A-IM 首部說明能夠接受的一些實例操控的類型。服務器在 IM 首部中說明使用的是何種實例操控。

在 IANA 註冊的實例操控類型:

  • vcdiff:用 vcdiff 算法計算差別
  • diffe:用 Unix 系統的 diff-e 命令計算差別
  • gdiff:用 gdiff 算法計算差別
  • gzip:用 gzip 算法壓縮
  • deflate:用 deflate 算法壓縮
  • range:用在服務器的響應中,說明響應是針對範圍選擇獲得的部份內容
  • identity:用在客戶端請求中的 A-IM 首部中,說明客戶端願意接受恆等實例操控
相關文章
相關標籤/搜索