HTTP 協議(網路協議篇一)
轉自https://www.jianshu.com/p/6e9e4156ece3
本篇文章篇幅比較長,先來個思維導圖預覽一下。
一張圖帶你看完本篇文章一、概述
1.計算機網路體系結構分層
計算機網路體系結構分層2.TCP/IP 通訊傳輸流
利用 TCP/IP 協議族進行網路通訊時,會通過分層順序與對方進行通訊。傳送端從應用層往下走,接收端則從鏈路層往上走。如下:
TCP/IP 通訊傳輸流- 首先作為傳送端的客戶端在應用層(HTTP 協議)發出一個想看某個 Web 頁面的 HTTP 請求。
- 接著,為了傳輸方便,在傳輸層(TCP 協議)把從應用層處收到的資料(HTTP 請求報文)進行分割,並在各個報文上打上標記序號及埠號後轉發給網路層。
- 在網路層(IP 協議),增加作為通訊目的地的 MAC 地址後轉發給鏈路層。這樣一來,發往網路的通訊請求就準備齊全了。
- 接收端的伺服器在鏈路層接收到資料,按序往上層傳送,一直到應用層。當傳輸到應用層,才能算真正接收到由客戶端傳送過來的 HTTP請求。
如下圖所示:
HTTP 請求在網路體系結構中,包含了眾多的網路協議,這篇文章主要圍繞 HTTP 協議(HTTP/1.1版本)展開。
HTTP協議(HyperText Transfer Protocol,超文字傳輸協議)是用於從WWW伺服器傳輸超文字到本地瀏覽器的傳輸協議。它可以使瀏覽器更加高效,使網路傳輸減少。它不僅保證計算機正確快速地傳輸超文字文件,還確定傳輸文件中的哪一部分,以及哪部分內容首先顯示(如文字先於圖形)等。
HTTP是客戶端瀏覽器或其他程式與Web伺服器之間的應用層通訊協議。在Internet上的Web伺服器上存放的都是超文字資訊,客戶機需要通過HTTP協議傳輸所要訪問的超文字資訊。HTTP包含命令和傳輸資訊,不僅可用於Web訪問,也可以用於其他因特網/內聯網應用系統之間的通訊,從而實現各類應用資源超媒體訪問的整合。
我們在瀏覽器的位址列裡輸入的網站地址叫做URL (Uniform Resource Locator,統一資源定位符)。就像每家每戶都有一個門牌地址一樣,每個網頁也都有一個Internet地址。當你在瀏覽器的地址框中輸入一個URL或是單擊一個超級連結時,URL就確定了要瀏覽的地址。瀏覽器通過超文字傳輸協議(HTTP),將Web伺服器上站點的網頁程式碼提取出來,並翻譯成漂亮的網頁。
二、HTTP 工作過程
HTTP請求響應模型HTTP通訊機制是在一次完整的 HTTP 通訊過程中,客戶端與伺服器之間將完成下列7個步驟:
-
建立 TCP 連線
在HTTP工作開始之前,客戶端首先要通過網路與伺服器建立連線,該連線是通過 TCP 來完成的,該協議與 IP 協議共同構建 Internet,即著名的 TCP/IP 協議族,因此 Internet 又被稱作是 TCP/IP 網路。HTTP 是比 TCP 更高層次的應用層協議,根據規則,只有低層協議建立之後,才能進行高層協議的連線,因此,首先要建立 TCP 連線,一般 TCP 連線的埠號是80; -
客戶端向伺服器傳送請求命令
一旦建立了TCP連線,客戶端就會向伺服器傳送請求命令;
例如:GET/sample/hello.jsp HTTP/1.1
-
客戶端傳送請求頭資訊
客戶端傳送其請求命令之後,還要以頭資訊的形式向伺服器傳送一些別的資訊,之後客戶端傳送了一空白行來通知伺服器,它已經結束了該頭資訊的傳送; -
伺服器應答
客戶端向伺服器發出請求後,伺服器會客戶端返回響應;
例如:HTTP/1.1 200 OK
響應的第一部分是協議的版本號和響應狀態碼 -
伺服器返回響應頭資訊
正如客戶端會隨同請求傳送關於自身的資訊一樣,伺服器也會隨同響應向用戶傳送關於它自己的資料及被請求的文件; -
伺服器向客戶端傳送資料
伺服器向客戶端傳送頭資訊後,它會發送一個空白行來表示頭資訊的傳送到此為結束,接著,它就以 Content-Type 響應頭資訊所描述的格式傳送使用者所請求的實際資料; -
伺服器關閉 TCP 連線
一般情況下,一旦伺服器向客戶端返回了請求資料,它就要關閉 TCP 連線,然後如果客戶端或者伺服器在其頭資訊加入了這行程式碼Connection:keep-alive
,TCP 連線在傳送後將仍然保持開啟狀態,於是,客戶端可以繼續通過相同的連線傳送請求。保持連線節省了為每個請求建立新連線所需的時間,還節約了網路頻寬。
三、HTTP 協議基礎
1.通過請求和響應的交換達成通訊
應用 HTTP 協議時,必定是一端擔任客戶端角色,另一端擔任伺服器端角色。僅從一條通訊線路來說,伺服器端和客服端的角色是確定的。HTTP 協議規定,請求從客戶端發出,最後伺服器端響應該請求並返回。換句話說,肯定是先從客戶端開始建立通訊的,伺服器端在沒有接收到請求之前不會發送響應。
2.HTTP 是不儲存狀態的協議
HTTP 是一種無狀態協議。協議自身不對請求和響應之間的通訊狀態進行儲存。也就是說在 HTTP 這個級別,協議對於傳送過的請求或響應都不做持久化處理。這是為了更快地處理大量事務,確保協議的可伸縮性,而特意把 HTTP 協議設計成如此簡單的。
可是隨著 Web 的不斷髮展,我們的很多業務都需要對通訊狀態進行儲存。於是我們引入了 Cookie 技術。有了 Cookie 再用 HTTP 協議通訊,就可以管理狀態了。
3.使用 Cookie 的狀態管理
Cookie 技術通過在請求和響應報文中寫入 Cookie 資訊來控制客戶端的狀態。Cookie 會根據從伺服器端傳送的響應報文內的一個叫做 Set-Cookie 的首部欄位資訊,通知客戶端儲存Cookie。當下次客戶端再往該伺服器傳送請求時,客戶端會自動在請求報文中加入 Cookie 值後傳送出去。伺服器端發現客戶端傳送過來的 Cookie 後,會去檢查究竟是從哪一個客戶端發來的連線請求,然後對比伺服器上的記錄,最後得到之前的狀態資訊。
Cookie 的流程
4.請求 URI 定位資源
HTTP 協議使用 URI 定位網際網路上的資源。正是因為 URI 的特定功能,在網際網路上任意位置的資源都能訪問到。
5.告知伺服器意圖的 HTTP 方法(HTTP/1.1)
HTTP 方法6.持久連線
HTTP 協議的初始版本中,每進行一個 HTTP 通訊都要斷開一次 TCP 連線。比如使用瀏覽器瀏覽一個包含多張圖片的 HTML 頁面時,在傳送請求訪問 HTML 頁面資源的同時,也會請求該 HTML 頁面裡包含的其他資源。因此,每次的請求都會造成無畏的 TCP 連線建立和斷開,增加通訊量的開銷。
為了解決上述 TCP 連線的問題,HTTP/1.1 和部分 HTTP/1.0 想出了持久連線的方法。其特點是,只要任意一端沒有明確提出斷開連線,則保持 TCP 連線狀態。旨在建立一次 TCP 連線後進行多次請求和響應的互動。在 HTTP/1.1 中,所有的連線預設都是持久連線。
7.管線化
持久連線使得多數請求以管線化方式傳送成為可能。以前傳送請求後需等待並接收到響應,才能傳送下一個請求。管線化技術出現後,不用等待亦可傳送下一個請求。這樣就能做到同時並行傳送多個請求,而不需要一個接一個地等待響應了。
比如,當請求一個包含多張圖片的 HTML 頁面時,與挨個連線相比,用持久連線可以讓請求更快結束。而管線化技術要比持久連線速度更快。請求數越多,時間差就越明顯。
四、HTTP 協議報文結構
1.HTTP 報文
用於 HTTP 協議互動的資訊被稱為 HTTP 報文。請求端(客戶端)的 HTTP 報文叫做請求報文;響應端(伺服器端)的叫做響應報文。HTTP 報文字身是由多行(用 CR+LF 作換行符)資料構成的字串文字。
2.HTTP 報文結構
HTTP 報文大致可分為報文首部和報文主體兩部分。兩者由最初出現的空行(CR+LF)來劃分。通常,並不一定有報文主體。如下:
HTTP 報文結構
2.1請求報文結構
請求報文結構請求報文的首部內容由以下資料組成:
- 請求行 —— 包含用於請求的方法、請求 URI 和 HTTP 版本。
- 首部欄位 —— 包含表示請求的各種條件和屬性的各類首部。(通用首部、請求首部、實體首部以及RFC裡未定義的首部如 Cookie 等)
請求報文的示例,如下:
請求報文示例
2.2響應報文結構
響應報文結構響應報文的首部內容由以下資料組成:
- 狀態行 —— 包含表明響應結果的狀態碼、原因短語和 HTTP 版本。
- 首部欄位 —— 包含表示請求的各種條件和屬性的各類首部。(通用首部、響應首部、實體首部以及RFC裡未定義的首部如 Cookie 等)
響應報文的示例,如下:
響應報文示例
五、HTTP 報文首部之請求行、狀態行
1.請求行
舉個栗子,下面是一個 HTTP 請求的報文:
GET /index.htm HTTP/1.1
Host: sample.com
其中,下面的這行就是請求行,
GET /index.htm HTTP/1.1
- 開頭的 GET 表示請求訪問伺服器的型別,稱為方法;
- 隨後的字串
/index.htm
指明瞭請求訪問的資源物件,也叫做請求 URI; - 最後的
HTTP/1.1
,即 HTTP 的版本號,用來提示客戶端使用的 HTTP 協議功能。
綜合來看,大意是請求訪問某臺 HTTP 伺服器上的 /index.htm
頁面資源。
2.狀態行
同樣舉個栗子,下面是一個 HTTP 響應的報文:
HTTP/1.1 200 OK
Date: Mon, 10 Jul 2017 15:50:06 GMT
Content-Length: 256
Content-Type: text/html
<html>
...
其中,下面的這行就是狀態行,
HTTP/1.1 200 OK
- 開頭的
HTTP/1.1
表示伺服器對應的 HTTP 版本; - 緊挨著的
200 OK
表示請求的處理結果的狀態碼和原因短語。
六、HTTP 報文首部之首部欄位(重點分析)
1.首部欄位概述
先來回顧一下首部欄位在報文的位置,HTTP 報文包含報文首部和報文主體,報文首部包含請求行(或狀態行)和首部欄位。
在報文眾多的欄位當中,HTTP 首部欄位包含的資訊最為豐富。首部欄位同時存在於請求和響應報文內,並涵蓋 HTTP 報文相關的內容資訊。使用首部欄位是為了給客服端和伺服器端提供報文主體大小、所使用的語言、認證資訊等內容。
2.首部欄位結構
- HTTP 首部欄位是由首部欄位名和欄位值構成的,中間用冒號“:”分隔。
- 另外,欄位值對應單個 HTTP 首部欄位可以有多個值。
- 當 HTTP 報文首部中出現了兩個或以上具有相同首部欄位名的首部欄位時,這種情況在規範內尚未明確,根據瀏覽器內部處理邏輯的不同,優先處理的順序可能不同,結果可能並不一致。
首部欄位名 | 冒號 | 欄位值 |
---|---|---|
Content-Type | : | text/html |
Keep-Alive | : | timeout=30, max=120 |
3.首部欄位型別
首部欄位根據實際用途被分為以下4種類型:
型別 | 描述 |
---|---|
通用首部欄位 | 請求報文和響應報文兩方都會使用的首部 |
請求首部欄位 | 從客戶端向伺服器端傳送請求報文時使用的首部。補充了請求的附加內容、客戶端資訊、響應內容相關優先順序等資訊 |
響應首部欄位 | 從伺服器端向客戶端返回響應報文時使用的首部。補充了響應的附加內容,也會要求客戶端附加額外的內容資訊。 |
實體首部欄位 | 針對請求報文和響應報文的實體部分使用的首部。補充了資源內容更新時間等與實體有關的的資訊。 |
4.通用首部欄位(HTTP/1.1)
首部欄位名 | 說明 |
---|---|
Cache-Control | 控制快取的行為 |
Connection | 逐挑首部、連線的管理 |
Date | 建立報文的日期時間 |
Pragma | 報文指令 |
Trailer | 報文末端的首部一覽 |
Transfer-Encoding | 指定報文主體的傳輸編碼方式 |
Upgrade | 升級為其他協議 |
Via | 代理伺服器的相關資訊 |
Warning | 錯誤通知 |
4.1 Cache-Control
通過指定首部欄位 Cache-Control 的指令,就能操作快取的工作機制。
4.1.1 可用的指令一覽
可用的指令按請求和響應分類如下:
快取請求指令
指令 | 引數 | 說明 |
---|---|---|
no-cache | 無 | 強制向伺服器再次驗證 |
no-store | 無 | 不快取請求或響應的任何內容 |
max-age = [秒] | 必需 | 響應的最大Age值 |
max-stale( =[秒]) | 可省略 | 接收已過期的響應 |
min-fresh = [秒] | 必需 | 期望在指定時間內的響應仍有效 |
no-transform | 無 | 代理不可更改媒體型別 |
only-if-cached | 無 | 從快取獲取資源 |
cache-extension | - | 新指令標記(token) |
快取響應指令
指令 | 引數 | 說明 |
---|---|---|
public | 無 | 可向任意方提供響應的快取 |
private | 可省略 | 僅向特定使用者返回響應 |
no-cache | 可省略 | 快取前必須先確認其有效性 |
no-store | 無 | 不快取請求或響應的任何內容 |
no-transform | 無 | 代理不可更改媒體型別 |
must-revalidate | 無 | 可快取但必須再向源伺服器進行確認 |
proxy-revalidate | 無 | 要求中間快取伺服器對快取的響應有效性再進行確認 |
max-age = [秒] | 必需 | 響應的最大Age值 |
s-maxage = [秒] | 必需 | 公共快取伺服器響應的最大Age值 |
cache-extension | - | 新指令標記(token) |
4.1.2 表示能否快取的指令
public 指令
Cache-Control: public
當指定使用 public 指令時,則明確表明其他使用者也可利用快取。
private 指令
Cache-Control: private
當指定 private 指令後,響應只以特定的使用者作為物件,這與 public 指令的行為相反。快取伺服器會對該特定使用者提供資源快取的服務,對於其他使用者傳送過來的請求,代理伺服器則不會返回快取。
no-cache 指令
Cache-Control: no-cache
- 使用 no-cache 指令是為了防止從快取中返回過期的資源。
- 客戶端傳送的請求中如果包含 no-cache 指令,則表示客戶端將不會接收快取過的響應。於是,“中間”的快取伺服器必須把客戶端請求轉發給源伺服器。
- 如果伺服器中返回的響應包含 no-cache 指令,那麼快取伺服器不能對資源進行快取。源伺服器以後也將不再對快取伺服器請求中提出的資源有效性進行確認,且禁止其對響應資源進行快取操作。
Cache-Control: no-cache=Location
由伺服器返回的響應中,若報文首部欄位 Cache-Control 中對 no-cache 欄位名具體指定引數值,那麼客戶端在接收到這個被指定引數值的首部欄位對應的響應報文後,就不能使用快取。換言之,無引數值的首部欄位可以使用快取。只能在響應指令中指定該引數。
no-store 指令
Cache-Control: no-store
當使用 no-store 指令時,暗示請求(和對應的響應)或響應中包含機密資訊。因此,該指令規定快取不能在本地儲存請求或響應的任一部分。
注意:no-cache 指令代表不快取過期的指令,快取會向源伺服器進行有效期確認後處理資源;no-store 指令才是真正的不進行快取。
4.1.3 指定快取期限和認證的指令
s-maxage 指令
Cache-Control: s-maxage=604800(單位:秒)
- s-maxage 指令的功能和 max-age 指令的相同,它們的不同點是 s-maxage 指令只適用於供多位使用者使用的公共快取伺服器(一般指代理)。也就是說,對於向同一使用者重複返回響應的伺服器來說,這個指令沒有任何作用。
- 另外,當使用 s-maxage 指令後,則直接忽略對 Expires 首部欄位及 max-age 指令的處理。
max-age 指令
Cache-Control: max-age=604800(單位:秒)
- 當客戶端傳送的請求中包含 max-age 指令時,如果判定快取資源的快取時間數值比指定的時間更小,那麼客戶端就接收快取的資源。另外,當指定 max-age 的值為0,那麼快取伺服器通常需要將請求轉發給源伺服器。
- 當伺服器返回的響應中包含 max-age 指令時,快取伺服器將不對資源的有效性再作確認,而 max-age 數值代表資源儲存為快取的最長時間。
- 應用 HTTP/1.1 版本的快取伺服器遇到同時存在 Expires 首部欄位的情況時,會優先處理 max-age 指令,並忽略掉 Expires 首部欄位;而 HTTP/1.0 版本的快取伺服器則相反。
min-fresh 指令
Cache-Control: min-fresh=60(單位:秒)
min-fresh 指令要求快取伺服器返回至少還未過指定時間的快取資源。
max-stale 指令
Cache-Control: max-stale=3600(單位:秒)
- 使用 max-stale 可指示快取資源,即使過期也照常接收。
- 如果指令未指定引數值,那麼無論經過多久,客戶端都會接收響應;如果指定了具體引數值,那麼即使過期,只要仍處於 max-stale 指定的時間內,仍舊會被客戶端接收。
only-if-cached 指令
Cache-Control: only-if-cached
表示客戶端僅在快取伺服器本地快取目標資源的情況下才會要求其返回。換言之,該指令要求快取伺服器不重新載入響應,也不會再次確認資源的有效性。
must-revalidate 指令
Cache-Control: must-revalidate
使用 must-revalidate 指令,代理會向源伺服器再次驗證即將返回的響應快取目前是否仍有效。另外,使用 must-revalidate 指令會忽略請求的 max-stale 指令。
proxy-revalidate 指令
Cache-Control: proxy-revalidate
proxy-revalidate 指令要求所有的快取伺服器在接收到客戶端帶有該指令的請求返回響應之前,必須再次驗證快取的有效性。
no-transform 指令
Cache-Control: no-transform
使用 no-transform 指令規定無論是在請求還是響應中,快取都不能改變實體主體的媒體型別。這樣做可防止快取或代理壓縮圖片等類似操作。
4.1.4 Cache-Control 擴充套件
Cache-Control: private, community="UCI"
通過 cache-extension 標記(token),可以擴充套件 Cache-Control 首部欄位內的指令。上述 community 指令即擴充套件的指令,如果快取伺服器不能理解這個新指令,就會直接忽略掉。
4.2 Connection
Connection 首部欄位具備以下兩個作用:
控制不再轉發的首部欄位
Connection: Upgrade
在客戶端傳送請求和伺服器返回響應中,使用 Connection 首部欄位,可控制不再轉發給代理的首部欄位,即刪除後再轉發(即Hop-by-hop首部)。
管理持久連線
Connection: close
HTTP/1.1 版本的預設連線都是持久連線。當伺服器端想明確斷開連線時,則指定 Connection 首部欄位的值為 close。
Connection: Keep-Alive
HTTP/1.1 之前的 HTTP 版本的預設連線都是非持久連線。為此,如果想在舊版本的 HTTP 協議上維持持續連線,則需要指定 Connection 首部欄位的值為 Keep-Alive。
4.3 Date
表明建立 HTTP 報文的日期和時間。
Date: Mon, 10 Jul 2017 15:50:06 GMT
HTTP/1.1 協議使用在 RFC1123 中規定的日期時間的格式。
4.4 Pragma
Pragma 首部欄位是 HTTP/1.1 版本之前的歷史遺留欄位,僅作為與 HTTP/1.0 的向後相容而定義。
Pragma: no-cache
- 該首部欄位屬於通用首部欄位,但只用在客戶端傳送的請求中,要求所有的中間伺服器不返回快取的資源。
- 所有的中間伺服器如果都能以 HTTP/1.1 為基準,那直接採用
Cache-Control: no-cache
指定快取的處理方式最為理想。但是要整體掌握所有中間伺服器使用的 HTTP 協議版本卻是不現實的,所以,傳送的請求會同時包含下面兩個首部欄位:
Cache-Control: no-cache
Pragma: no-cache
4.5 Trailer
Trailer: Expires
首部欄位 Trailer 會事先說明在報文主體後記錄了哪些首部欄位。可應用在 HTTP/1.1 版本分塊傳輸編碼時。
4.6 Transfer-Encoding
Transfer-Encoding: chunked
- 規定了傳輸報文主體時採用的編碼方式。
- HTTP/1.1 的傳輸編碼方式僅對分塊傳輸編碼有效。
4.7 Upgrade
Upgrade: TSL/1.0
用於檢測 HTTP 協議及其他協議是否可使用更高的版本進行通訊,其引數值可以用來指定一個完全不同的通訊協議。
4.8 Via
Via: 1.1 a1.sample.com(Squid/2.7)
- 為了追蹤客戶端和伺服器端之間的請求和響應報文的傳輸路徑。
- 報文經過代理或閘道器時,會現在首部欄位 Via 中附加該伺服器的資訊,然後再進行轉發。
- 首部欄位 Via 不僅用於追蹤報文的轉發,還可避免請求迴環的發生。
4.9 Warning
該首部欄位通常會告知使用者一些與快取相關的問題的警告。
Warning 首部欄位的格式如下:
Warning:[警告碼][警告的主機:埠號] "[警告內容]"([日期時間])
最後的日期時間可省略。
HTTP/1.1 中定義了7種警告,警告碼對應的警告內容僅推薦參考,另外,警告碼具備擴充套件性,今後有可能追加新的警告碼。
警告碼 | 警告內容 | 說明 |
---|---|---|
110 | Response is stale(響應已過期) | 代理返回已過期的資源 |
111 | Revalidation failed(再驗證失敗) | 代理再驗證資源有效性時失敗(伺服器無法到達等原因) |
112 | Disconnection operation(斷開連線操作) | 代理與網際網路連線被故意切斷 |
113 | Heuristic expiration(試探性過期) | 響應的試用期超過24小時(有效快取的設定時間大於24小時的情況下) |
199 | Miscellaneous warning(雜項警告) | 任意的警告內容 |
214 | Transformation applied(使用了轉換) | 代理對內容編碼或媒體型別等執行了某些處理時 |
299 | Miscellaneous persistent warning(持久雜項警告) | 任意的警告內容 |
5. 請求首部欄位(HTTP/1.1)
首部欄位名 | 說明 |
---|---|
Accept | 使用者代理可處理的媒體型別 |
Accept-Charset | 優先的字符集 |
Accept-Encoding | 優先的內容編碼 |
Accept-Language | 優先的語言(自然語言) |
Authorization | Web認證資訊 |
Expect | 期待伺服器的特定行為 |
From | 使用者的電子郵箱地址 |
Host | 請求資源所在伺服器 |
If-Match | 比較實體標記(ETag) |
If-Modified-Since | 比較資源的更新時間 |
If-None-Match | 比較實體標記(與 If-Macth 相反) |
If-Range | 資源未更新時傳送實體 Byte 的範圍請求 |
If-Unmodified-Since | 比較資源的更新時間(與 If-Modified-Since 相反) |
Max-Forwards | 最大傳輸逐跳數 |
Proxy-Authorization | 代理伺服器要求客戶端的認證資訊 |
Range | 實體的位元組範圍請求 |
Referer | 對請求中 URI 的原始獲取方 |
TE | 傳輸編碼的優先順序 |
User-Agent | HTTP 客戶端程式的資訊 |
5.1 Accept
Accept: text/html, application/xhtml+xml, application/xml; q=0.5
- Accept 首部欄位可通知伺服器,使用者代理能夠處理的媒體型別及媒體型別的相對優先順序。可使用 type/subtype 這種形式,一次指定多種媒體型別。
- 若想要給顯示的媒體型別增加優先順序,則使用
q=[數值]
來表示權重值,用分號(;)進行分隔。權重值的範圍 0~1(可精確到小數點後三位),且 1 為最大值。不指定權重值時,預設為 1。
5.2 Accept-Charset
Accept-Charset: iso-8859-5, unicode-1-1; q=0.8
Accept-Charset 首部欄位可用來通知伺服器使用者代理支援的字符集及字符集的相對優先順序。另外,可一次性指定多種字符集。同樣使用 q=[數值]
來表示相對優先順序。
5.3 Accept-Encoding
Accept-Encoding: gzip, deflate
Accept-Encoding 首部欄位用來告知伺服器使用者代理支援的內容編碼及內容編碼的優先順序,並可一次性指定多種內容編碼。同樣使用 q=[數值]
來表示相對優先順序。也可使用星號(*)作為萬用字元,指定任意的編碼格式。
5.4 Accept-Language
Accept-Lanuage: zh-cn,zh;q=0.7,en=us,en;q=0.3
告知伺服器使用者代理能夠處理的自然語言集(指中文或英文等),以及自然語言集的相對優先順序,可一次性指定多種自然語言集。同樣使用 q=[數值]
來表示相對優先順序。
5.5 Authorization
Authorization: Basic ldfKDHKfkDdasSAEdasd==
告知伺服器使用者代理的認證資訊(證書值)。通常,想要通過伺服器認證的使用者代理會在接收到返回的 401 狀態碼響應後,把首部欄位 Authorization 加入請求中。共用快取在接收到含有 Authorization 首部欄位的請求時的操作處理會略有差異。
5.6 Expect
Expect: 100-continue
告知伺服器客戶端期望出現的某種特定行為。
5.7 From
From: [email protected]
告知伺服器使用使用者代理的電子郵件地址。
5.8 Host
Host: www.jianshu.com
- 告知伺服器,請求的資源所處的網際網路主機和埠號。
- Host 首部欄位是 HTTP/1.1 規範內唯一一個必須被包含在請求內的首部欄位。
- 若伺服器未設定主機名,那直接傳送一個空值即可
Host:
。
5.9 If-Match
形如 If-xxx 這種樣式的請求首部欄位,都可稱為條件請求。伺服器接收到附帶條件的請求後,只有判斷指定條件為真時,才會執行請求。
If-Match: "123456"
- 首部欄位 If-Match,屬附帶條件之一,它會告知伺服器匹配資源所用的實體標記(ETag)值。這時的伺服器無法使用弱 ETag 值。
- 伺服器會比對 If-Match 的欄位值和資源的 ETag 值,僅當兩者一致時,才會執行請求。反之,則返回狀態碼
412 Precondition Failed
的響應。 - 還可以使用星號(*)指定 If-Match 的欄位值。針對這種情況,伺服器將會忽略 ETag 的值,只要資源存在就處理請求。
5.10 If-Modified-Since
If-Modified-Since: Mon, 10 Jul 2017 15:50:06 GMT
- 首部欄位 If-Modified-Since,屬附帶條件之一,用於確認代理或客戶端擁有的本地資源的有效性。
- 它會告知伺服器若 If-Modified-Since 欄位值早於資源的更新時間,則希望能處理該請求。而在指定 If-Modified-Since 欄位值的日期時間之後,如果請求的資源都沒有過更新,則返回狀態碼
304 Not Modified
的響應。
5.11 If-None-Match
If-None-Match: "123456"
首部欄位 If-None-Match 屬於附帶條件之一。它和首部欄位 If-Match 作用相反。用於指定 If-None-Match 欄位值的實體標記(ETag)值與請求資源的 ETag 不一致時,它就告知伺服器處理該請求。
5.12 If-Range
If-Range: "123456"
- 首部欄位 If-Range 屬於附帶條件之一。它告知伺服器若指定的 If-Range 欄位值(ETag 值或者時間)和請求資源的 ETag 值或時間相一致時,則作為範圍請求處理。反之,則返回全體資源。
- 下面我們思考一下不使用首部欄位 If-Range 傳送請求的情況。伺服器端的資源如果更新,那客戶端持有資源中的一部分也會隨之無效,當然,範圍請求作為前提是無效的。這時,伺服器會暫且以狀態碼
412 Precondition Failed
作為響應返回,其目的是催促客戶端再次傳送請求。這樣一來,與使用首部欄位 If-Range 比起來,就需要花費兩倍的功夫。
5.13 If-Unmodified-Since
If-Unmodified-Since: Mon, 10 Jul 2017 15:50:06 GMT
首部欄位 If-Unmodified-Since 和首部欄位 If-Modified-Since 的作用相反。它的作用的是告知伺服器,指定的請求資源只有在欄位值內指定的日期時間之後,未發生更新的情況下,才能處理請求。如果在指定日期時間後發生了更新,則以狀態碼 412 Precondition Failed
作為響應返回。
5.14 Max-Forwards
Max-Forwards: 10
通過 TRACE 方法或 OPTIONS 方法,傳送包含首部欄位 Max-Forwards 的請求時,該欄位以十進位制整數形式指定可經過的伺服器最大數目。伺服器在往下一個伺服器轉發請求之前,Max-Forwards 的值減 1 後重新賦值。當伺服器接收到 Max-Forwards 值為 0 的請求時,則不再進行轉發,而是直接返回響應。
5.15 Proxy-Authorization
Proxy-Authorization: Basic dGlwOjkpNLAGfFY5
- 接收到從代理伺服器發來的認證質詢時,客戶端會發送包含首部欄位 Proxy-Authorization 的請求,以告知伺服器認證所需要的資訊。
- 這個行為是與客戶端和伺服器之間的 HTTP 訪問認證相類似的,不同之處在於,認證行為發生在客戶端與代理之間。
5.16 Range
Range: bytes=5001-10000
- 對於只需獲取部分資源的範圍請求,包含首部欄位 Range 即可告知伺服器資源的指定範圍。
- 接收到附帶 Range 首部欄位請求的伺服器,會在處理請求之後返回狀態碼為
206 Partial Content
的響應。無法處理該範圍請求時,則會返回狀態碼200 OK
的響應及全部資源。
5.17 Referer
Referer: http://www.sample.com/index.html
首部欄位 Referer 會告知伺服器請求的原始資源的 URI。
5.18 TE
TE: gzip, deflate; q=0.5
- 首部欄位 TE 會告知伺服器客戶端能夠處理響應的傳輸編碼方式及相對優先順序。它和首部欄位 Accept-Encoding 的功能很相像,但是用於傳輸編碼。
- 首部欄位 TE 除指定傳輸編碼之外,還可以指定伴隨 trailer 欄位的分塊傳輸編碼的方式。應用後者時,只需把 trailers 賦值給該欄位值。
TE: trailers
5.19 User-Agent
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:13.0) Gecko/20100101
- 首部欄位 User-Agent 會將建立請求的瀏覽器和使用者代理名稱等資訊傳達給伺服器。
- 由網路爬蟲發起請求時,有可能會在欄位內新增爬蟲作者的電子郵件地址。此外,如果請求經過代理,那麼中間也很可能被新增上代理伺服器的名稱。
6. 響應首部欄位(HTTP/1.1)
首部欄位名 | 說明 |
---|---|
Accept-Ranges | 是否接受位元組範圍請求 |
Age | 推算資源建立經過時間 |
ETag | 資源的匹配資訊 |
Location | 令客戶端重定向至指定 URI |
Proxy-Authenticate | 代理伺服器對客戶端的認證資訊 |
Retry-After | 對再次發起請求的時機要求 |
Server | HTTP 伺服器的安裝資訊 |
Vary | 代理伺服器快取的管理資訊 |
WWW-Authenticate | 伺服器對客戶端的認證資訊 |
6.1 Accept-Ranges
Accept-Ranges: bytes
- 首部欄位 Accept-Ranges 是用來告知客戶端伺服器是否能處理範圍請求,以指定獲取伺服器端某個部分的資源。
- 可指定的欄位值有兩種,可處理範圍請求時指定其為 bytes,反之則指定其為 none。
6.2 Age
Age: 1200
- 首部欄位 Age 能告知客戶端,源伺服器在多久前建立了響應。欄位值的單位為秒。
- 若建立該響應的伺服器是快取伺服器,Age 值是指快取後的響應再次發起認證到認證完成的時間值。代理建立響應時必須加上首部欄位 Age。
6.3 ETag
ETag: "usagi-1234"
- 首部欄位 ETag 能告知客戶端實體標識。它是一種可將資源以字串形式做唯一性標識的方式。伺服器會為每份資源分配對應的 ETag 值。
- 另外,當資源更新時,ETag 值也需要更新。生成 ETag 值時,並沒有統一的演算法規則,而僅僅是由伺服器來分配。
- ETag 中有強 ETag 值和弱 ETag 值之分。強 ETag 值,不論實體發生多麼細微的變化都會改變其值;弱 ETag 值只用於提示資源是否相同。只有資源發生了根本改變,產生差異時才會改變 ETag 值。這時,會在欄位值最開始處附加 W/:
ETag: W/"usagi-1234"
。
6.4 Location
Location: http://www.sample.com/sample.html
- 使用首部欄位 Location 可以將響應接收方引導至某個與請求 URI 位置不同的資源。
- 基本上,該欄位會配合 3xx :Redirection 的響應,提供重定向的 URI。
- 幾乎所有的瀏覽器在接收到包含首部欄位 Location 的響應後,都會強制性地嘗試對已提示的重定向資源的訪問。
6.5 Proxy-Authenticate
Proxy-Authenticate: Basic realm="Usagidesign Auth"
- 首部欄位 Proxy-Authenticate 會把由代理伺服器所要求的認證資訊傳送給客戶端。
- 它與客戶端和伺服器之間的 HTTP 訪問認證的行為相似,不同之處在於其認證行為是在客戶端與代理之間進行的。
6.6 Retry-After
Retry-After: 180
- 首部欄位 Retry-After 告知客戶端應該在多久之後再次傳送請求。主要配合狀態碼
503 Service Unavailable
響應,或 3xx Redirect 響應一起使用。 - 欄位值可以指定為具體的日期時間(Mon, 10 Jul 2017 15:50:06 GMT 等格式),也可以是建立響應後的秒數。
6.7 Server
Server: Apache/2.2.6 (Unix) PHP/5.2.5
首部欄位 Server 告知客戶端當前伺服器上安裝的 HTTP 伺服器應用程式的資訊。不單單會標出伺服器上的軟體應用名稱,還有可能包括版本號和安裝時啟用的可選項。
6.8 Vary
Vary: Accept-Language
- 首部欄位 Vary 可對快取進行控制。源伺服器會向代理伺服器傳達關於本地快取使用方法的命令。
- 從代理伺服器接收到源伺服器返回包含 Vary 指定項的響應之後,若再要進行快取,僅對請求中含有相同 Vary 指定首部欄位的請求返回快取。即使對相同資源發起請求,但由於 Vary 指定的首部欄位不相同,因此必須要從源伺服器重新獲取資源。
6.9 WWW-Authenticate
WWW-Authenticate: Basic realm="Usagidesign Auth"
首部欄位 WWW-Authenticate 用於 HTTP 訪問認證。它會告知客戶端適用於訪問請求 URI 所指定資源的認證方案(Basic 或是 Digest)和帶引數提示的質詢(challenge)。
7. 實體首部欄位(HTTP/1.1)
首部欄位名 | 說明 |
---|---|
Allow | 資源可支援的 HTTP 方法 |
Content-Encoding | 實體主體適用的編碼方式 |
Content-Language | 實體主體的自然語言 |
Content-Length | 實體主體的大小(單位:位元組) |
Content-Location | 替代對應資源的 URI |
Content-MD5 | 實體主體的報文摘要 |
Content-Range | 實體主體的位置範圍 |
Content-Type | 實體主體的媒體型別 |
Expires | 實體主體過期的日期時間 |
Last-Modified | 資源的最後修改日期時間 |
7.1 Allow
Allow: GET, HEAD
- 首部欄位 Allow 用於通知客戶端能夠支援 Request-URI 指定資源的所有 HTTP 方法。
- 當伺服器接收到不支援的 HTTP 方法時,會以狀態碼
405 Method Not Allowed
作為響應返回。與此同時,還會把所有能支援的 HTTP 方法寫入首部欄位 Allow 後返回。
7.2 Content-Encoding
Content-Encoding: gzip
- 首部欄位 Content-Encoding 會告知客戶端伺服器對實體的主體部分選用的內容編碼方式。內容編碼是指在不丟失實體資訊的前提下所進行的壓縮。
- 主要採用這 4 種內容編碼的方式(gzip、compress、deflate、identity)。
7.3 Content-Language
Content-Language: zh-CN
首部欄位 Content-Language 會告知客戶端,實體主體使用的自然語言(指中文或英文等語言)。
7.4 Content-Length
Content-Length: 15000
首部欄位 Content-Length 表明了實體主體部分的大小(單位是位元組)。對實體主體進行內容編碼傳輸時,不能再使用 Content-Length首部欄位。
7.5 Content-Location
Content-Location: http://www.sample.com/index.html
首部欄位 Content-Location 給出與報文主體部分相對應的 URI。和首部欄位 Location 不同,Content-Location 表示的是報文主體返回資源對應的 URI。
7.6 Content-MD5
Content-MD5: OGFkZDUwNGVhNGY3N2MxMDIwZmQ4NTBmY2IyTY==
首部欄位 Content-MD5 是一串由 MD5 演算法生成的值,其目的在於檢查報文主體在傳輸過程中是否保持完整,以及確認傳輸到達。
7.7 Content-Range
Content-Range: bytes 5001-10000/10000
針對範圍請求,返回響應時使用的首部欄位 Content-Range,能告知客戶端作為響應返回的實體的哪個部分符合範圍請求。欄位值以位元組為單位,表示當前傳送部分及整個實體大小。
7.8 Content-Type
Content-Type: text/html; charset=UTF-8
首部欄位 Content-Type 說明了實體主體內物件的媒體型別。和首部欄位 Accept 一樣,欄位值用 type/subtype 形式賦值。引數 charset 使用 iso-8859-1 或 euc-jp 等字符集進行賦值。
7.9 Expires
Expires: Mon, 10 Jul 2017 15:50:06 GMT
- 首部欄位 Expires 會將資源失效的日期告知客戶端。
- 快取伺服器在接收到含有首部欄位 Expires 的響應後,會以快取來應答請求,在 Expires 欄位值指定的時間之前,響應的副本會一直被儲存。當超過指定的時間後,快取伺服器在請求傳送過來時,會轉向源伺服器請求資源。
- 源伺服器不希望快取伺服器對資源快取時,最好在 Expires 欄位內寫入與首部欄位 Date 相同的時間值。
7.10 Last-Modified
Last-Modified: Mon, 10 Jul 2017 15:50:06 GMT
首部欄位 Last-Modified 指明資源最終修改的時間。一般來說,這個值就是 Request-URI 指定資源被修改的時間。但類似使用 CGI 指令碼進行動態資料處理時,該值有可能會變成資料最終修改時的時間。
8. 為 Cookie 服務的首部欄位
首部欄位名 | 說明 | 首部型別 |
---|---|---|
Set-Cookie | 開始狀態管理所使用的 Cookie 資訊 | 響應首部欄位 |
Cookie | 伺服器接收到的 Cookie 資訊 | 請求首部欄位 |
8.1 Set-Cookie
Set-Cookie: status=enable; expires=Mon, 10 Jul 2017 15:50:06 GMT; path=/;
下面的表格列舉了 Set-Cookie 的欄位值。
屬性 | 說明 |
---|---|
NAME=VALUE | 賦予 Cookie 的名稱和其值(必需項) |
expires=DATE | Cookie 的有效期(若不明確指定則預設為瀏覽器關閉前為止) |
path=PATH | 將伺服器上的檔案目錄作為Cookie的適用物件(若不指定則預設為文件所在的檔案目錄) |
domain=域名 | 作為 Cookie 適用物件的域名 (若不指定則預設為建立 Cookie的伺服器的域名) |
Secure | 僅在 HTTPS 安全通訊時才會傳送 Cookie |
HttpOnly | 加以限制,使 Cookie 不能被 JavaScript 指令碼訪問 |
8.1.1 expires 屬性
- Cookie 的 expires 屬性指定瀏覽器可傳送 Cookie 的有效期。
- 當省略 expires 屬性時,其有效期僅限於維持瀏覽器會話(Session)時間段內。這通常限於瀏覽器應用程式被關閉之前。
- 另外,一旦 Cookie 從伺服器端傳送至客戶端,伺服器端就不存在可以顯式刪除 Cookie 的方法。但可通過覆蓋已過期的 Cookie,實現對客戶端 Cookie 的實質性刪除操作。
8.1.2 path 屬性
Cookie 的 path 屬性可用於限制指定 Cookie 的傳送範圍的檔案目錄。
8.1.3 domain 屬性
- 通過 Cookie 的 domain 屬性指定的域名可做到與結尾匹配一致。比如,當指定 example.com 後,除example.com 以外,www.example.com 或 www2.example.com 等都可以傳送 Cookie。
- 因此,除了針對具體指定的多個域名傳送 Cookie 之 外,不指定 domain 屬性顯得更安全。
8.1.4 secure 屬性
Cookie 的 secure 屬性用於限制 Web 頁面僅在 HTTPS 安全連線時,才可以傳送 Cookie。
8.1.5 HttpOnly 屬性
- Cookie 的 HttpOnly 屬性是 Cookie 的擴充套件功能,它使 JavaScript 指令碼無法獲得 Cookie。其主要目的為防止跨站指令碼攻擊(Cross-site scripting,XSS)對 Cookie 的資訊竊取。
- 通過上述設定,通常從 Web 頁面內還可以對 Cookie 進行讀取操作。但使用 JavaScript 的 document.cookie 就無法讀取附加 HttpOnly 屬性後的 Cookie 的內容了。因此,也就無法在 XSS 中利用 JavaScript 劫持 Cookie 了。
8.2 Cookie
Cookie: status=enable
首部欄位 Cookie 會告知伺服器,當客戶端想獲得 HTTP 狀態管理支援時,就會在請求中包含從伺服器接收到的 Cookie。接收到多個 Cookie 時,同樣可以以多個 Cookie 形式傳送。
9. 其他首部欄位
HTTP 首部欄位是可以自行擴充套件的。所以在 Web 伺服器和瀏覽器的應用上,會出現各種非標準的首部欄位。
以下是最為常用的首部欄位。
9.1 X-Frame-Options
X-Frame-Options: DENY
首部欄位 X-Frame-Options 屬於 HTTP 響應首部,用於控制網站內容在其他 Web 網站的 Frame 標籤內的顯示問題。其主要目的是為了防止點選劫持(clickjacking)攻擊。首部欄位 X-Frame-Options 有以下兩個可指定的欄位值:
- DENY:拒絕
- SAMEORIGIN:僅同源域名下的頁面(Top-level-browsing-context)匹配時許可。(比如,當指定 http://sample.com/sample.html 頁面為 SAMEORIGIN 時,那麼 sample.com 上所有頁面的 frame 都被允許可載入該頁面,而 example.com 等其他域名的頁面就不行了)
9.2 X-XSS-Protection
X-XSS-Protection: 1
首部欄位 X-XSS-Protection 屬於 HTTP 響應首部,它是針對跨站指令碼攻擊(XSS)的一種對策,用於控制瀏覽器 XSS 防護機制的開關。首部欄位 X-XSS-Protection 可指定的欄位值如下:
- 0 :將 XSS 過濾設定成無效狀態
- 1 :將 XSS 過濾設定成有效狀態
9.3 DNT
DNT: 1
首部欄位 DNT 屬於 HTTP 請求首部,其中 DNT 是 Do Not Track 的簡稱,意為拒絕個人資訊被收集,是表示拒絕被精準廣告追蹤的一種方法。首部欄位 DNT 可指定的欄位值如下:
- 0 :同意被追蹤
- 1 :拒絕被追蹤
由於首部欄位 DNT 的功能具備有效性,所以 Web 伺服器需要對 DNT做對應的支援。
9.4 P3P
P3P: CP="CAO DSP LAW CURa ADMa DEVa TAIa PSAa PSDa IVAa IVDa OUR BUS IND
首部欄位 P3P 屬於 HTTP 響應首部,通過利用 P3P(The Platform for Privacy Preferences,線上隱私偏好平臺)技術,可以讓 Web 網站上的個人隱私變成一種僅供程式可理解的形式,以達到保護使用者隱私的目的。
要進行 P3P 的設定,需按以下操作步驟進行:
- 步驟 1:建立 P3P 隱私
- 步驟 2:建立 P3P 隱私對照檔案後,儲存命名在 /w3c/p3p.xml
- 步驟 3:從 P3P 隱私中新建 Compact policies 後,輸出到 HTTP 響應中
七、HTTP 響應狀態碼(重點分析)
1. 狀態碼概述
- HTTP 狀態碼負責表示客戶端 HTTP 請求的返回結果、標記伺服器端的處理是否正常、通知出現的錯誤等工作。
- HTTP 狀態碼如
200 OK
,以 3 位數字和原因短語組成。數字中的第一位指定了響應類別,後兩位無分類。 - 不少返回的響應狀態碼都是錯誤的,但是使用者可能察覺不到這點。比如 Web 應用程式內部發生錯誤,狀態碼依然返回
200 OK
。
2. 狀態碼類別
類別 | 原因短語 | |
---|---|---|
1xx | Informational(資訊性狀態碼) | 接收的請求正在處理 |
2xx | Success(成功狀態碼) | 請求正常處理完畢 |
3xx | Redirection(重定向狀態碼) | 需要進行附加操作以完成請求 |
4xx | Client Error(客戶端錯誤狀態碼) | 伺服器無法處理請求 |
5xx | Server Error(伺服器錯誤狀態碼) | 伺服器處理請求出錯 |
我們可以自行改變 RFC2616 中定義的狀態碼或者伺服器端自行建立狀態碼,只要遵守狀態碼的類別定義就可以了。
3. 常用狀態碼解析
HTTP 狀態碼種類繁多,數量達幾十種。其中最常用的有以下 14 種,一起來看看。
3.1 200 OK
表示從客戶端發來的請求在伺服器端被正常處理了。
3.2 204 No Content
- 代表伺服器接收的請求已成功處理,但在返回的響應報文中不含實體的主體部分。另外,也不允許返回任何實體的主體。
- 一般在只需要從客戶端向伺服器端傳送訊息,而伺服器端不需要向客戶端傳送新訊息內容的情況下使用。
3.3 206 Partial Content
表示客戶端進行了範圍請求,而伺服器成功執行了這部分的 GET 請求。響應報文中包含由 Content-Range 首部欄位指定範圍的實體內容。
3.4 301 Moved Permanently
永久性重定向。表示請求的資源已被分配了新的 URI。以後應使用資源現在所指的 URI。也就是說,如果已經把資源對應的 URI 儲存為書籤了,這時應該按 Location 首部欄位提示的 URI 重新儲存。
3.5 302 Found
- 臨時性重定向。表示請求的資源已被分配了新的 URI,希望使用者(本次)能使用新的 URI 訪問。
- 和
301 Moved Permanently
狀態碼相似,但302 Found
狀態碼代表資源不是被永久移動,只是臨時性質的。換句話說,已移動的資源對應的 URI 將來還有可能發生改變。
3.6 303 See Other
- 表示由於請求的資源存在著另一個 URI,應使用 GET 方法定向獲取請求的資源。
-
303 See Othe
r 和302 Found
狀態碼有著相同的功能,但303 See Other
狀態碼明確表示客戶端應採用 GET 方法獲取資源,這點與302 Found
狀態碼有區別。
3.7 304 Not Modified
- 表示客戶端傳送附帶條件的請求時,伺服器端允許請求訪問的資源,但未滿足條件的情況。
-
304 Not Modified
狀態碼返回時,不包含任何響應的主體部分。 -
304 Not Modified
雖然被劃分到 3xx 類別中,但和重定向沒有關係。
3.8 307 Temporary Redirect
臨時重定向。該狀態碼與 302 Found
有著相同的含義。
3.9 400 Bad Request
- 表示請求報文中存在語法錯誤。當錯誤發生時,需修改請求的內容後再次傳送請求。
- 另外,瀏覽器會像
200 OK
一樣對待該狀態碼。
3.10 401 Unauthorized
- 表示傳送的請求需要有通過 HTTP 認證(BASIC 認證、DIGEST 認證)的認證資訊。
- 另外,若之前已進行過 1 次請求,則表示使用者認證失敗。
- 返回含有
401 Unauthorized
的響應必須包含一個適用於被請求資源的 WWW-Authenticate 首部用以質詢(challenge)使用者資訊。
3.11 403 Forbidden
表明對請求資源的訪問被伺服器拒絕了。伺服器端沒有必要給出詳細的拒絕理由,當然也可以在響應報文的實體主體部分對原因進行描述。
3.12 404 Not Found
表明伺服器上無法找到請求的資源。除此之外,也可以在伺服器端拒絕請求且不想說明理由的時候使用。
3.13 500 Internal Server Error
表明伺服器端在執行請求時發生了錯誤。也可能是 Web 應用存在的 bug 或某些臨時的故障。
3.14 503 Service Unavailable
表明伺服器暫時處於超負載或正在進行停機維護,現在無法處理請求。如果事先得知解除以上狀況需要的時間,最好寫入 Retry-After 首部欄位再返回給客戶端。
八、HTTP 報文實體
1. HTTP 報文實體概述
HTTP 報文結構大家請仔細看看上面示例中,各個組成部分對應的內容。
接著,我們來看看報文和實體的概念。如果把 HTTP 報文想象成因特網貨運系統中的箱子,那麼 HTTP 實體就是報文中實際的貨物。
- 報文:是網路中交換和傳輸的資料單元,即站點一次性要傳送的資料塊。報文包含了將要傳送的完整的資料資訊,其長短很不一致,長度不限且可變。
- 實體:作為請求或響應的有效載荷資料(補充項)被傳輸,其內容由實體首部和實體主體組成。(實體首部相關內容在上面第六點中已有闡述。)
我們可以看到,上面示例右圖中深紅色框的內容就是報文的實體部分,而藍色框的兩部分內容分別就是實體首部和實體主體。而左圖中粉紅框內容就是報文主體。
通常,報文主體等於實體主體。只有當傳輸中進行編碼操作時,實體主體的內容發生變化,才導致它和報文主體產生差異。
2. 內容編碼
- HTTP 應用程式有時在傳送之前需要對內容進行編碼。例如,在把很大的 HTML 文件傳送給通過慢速連線上來的客戶端之前,伺服器可能會對其進行壓縮,這樣有助於減少傳輸實體的時間。伺服器還可以把內容攪亂或加密,以此來防止未授權的第三方看到文件的內容。
- 這種型別的編碼是在傳送方應用到內容之上的。當內容經過內容編碼後,編好碼的資料就放在實體主體中,像往常一樣傳送給接收方。
內容編碼型別:
編碼方式 | 描述 |
---|---|
gzip | 表明實體採用 GNU zip 編碼 |
compress | 表明實體採用 Unix 的檔案壓縮程式 |
deflate | 表明實體採用 zlib 的格式壓縮的 |
identity | 表明沒有對實體進行編碼,當沒有 Content-Encoding 首部欄位時,預設採用此編碼方式 |
3. 傳輸編碼
內容編碼是對報文的主體進行的可逆變換,是和內容的具體格式細節緊密相關的。
傳輸編碼也是作用在實體主體上的可逆變換,但使用它們是由於架構方面的原因,同內容的格式無關。使用傳輸編碼是為了改變報文中的資料在網路上傳輸的方式。
內容編碼和傳輸編碼的對比
4. 分塊編碼
分塊編碼把報文分割成若干已知大小的塊。塊之間是緊挨著傳送的,這樣就不需要在傳送之前知道整個報文的大小了。分塊編碼是一種傳輸編碼,是報文的屬性。
分塊編碼與持久連線
若客戶端與伺服器端之間不是持久連線,客戶端就不需要知道它在讀取的主體的長度,而只需要讀取到伺服器關閉主體連線為止。
當使用持久連線時,在伺服器寫主體之前,必須知道它的大小並在 Content-Length 首部中傳送。如果伺服器動態建立內容,就可能在傳送之前無法知道主體的長度。
分塊編碼為這種困難提供瞭解決方案,只要允許伺服器把主體分塊傳送,說明每塊的大小就可以了。因為主體是動態建立的,伺服器可以緩衝它的一部分,傳送其大小和相應的塊,然後在主體傳送完之前重複這個過程。伺服器可以用大小為 0 的塊作為主體結束的訊號,這樣就可以繼續保持連線,為下一個響應做準備。
來看看一個分塊編碼的報文示例:
5.多部分媒體型別
MIME 中的 multipart(多部分)電子郵件報文中包含多個報文,它們合在一起作為單一的複雜報文傳送。每一部分都是獨立的,有各自的描述其內容的集,不同部分之間用分界字串連線在一起。
相應得,HTTP 協議中也採納了多部分物件集合,傳送的一份報文主體內可包含多種型別實體。
多部分物件集合包含的物件如下:
- multipart/form-data:在 Web 表單檔案上傳時使用。
- multipart/byteranges:狀態碼
206 Partial Content
響應報文包含了多個範圍的內容時使用。
6. 範圍請求
假設你正在下載一個很大的檔案,已經下了四分之三,忽然網路中斷了,那下載就必須重頭再來一遍。為了解決這個問題,需要一種可恢復的機制,即能從之前下載中斷處恢復下載。要實現該功能,這就要用到範圍請求。
有了範圍請求, HTTP 客戶端可以通過請求曾獲取失敗的實體的一個範圍(或者說一部分),來恢復下載該實體。當然這有一個前提,那就是從客戶端上一次請求該實體到這一次發出範圍請求的時間段內,該物件沒有改變過。例如:
GET /bigfile.html HTTP/1.1
Host: www.sample.com
Range: bytes=20224-
···
實體範圍請求示例
上面示例中,客戶端請求的是文件開頭20224位元組之後的部分。
九、與 HTTP 協作的 Web 伺服器
HTTP 通訊時,除客戶端和伺服器外,還有一些用於協助通訊的應用程式。如下列出比較重要的幾個:代理、快取、閘道器、隧道、Agent 代理。
1.代理
代理HTTP 代理伺服器是 Web 安全、應用整合以及效能優化的重要組成模組。代理位於客戶端和伺服器端之間,接收客戶端所有的 HTTP 請求,並將這些請求轉發給伺服器(可能會對請求進行修改之後再進行轉發)。對使用者來說,這些應用程式就是一個代理,代表使用者訪問伺服器。
出於安全考慮,通常會將代理作為轉發所有 Web 流量的可信任中間節點使用。代理還可以對請求和響應進行過濾,安全上網或綠色上網。
2. 快取
瀏覽器第一次請求:
瀏覽器再次請求:
Web 快取或代理快取是一種特殊的 HTTP 代理伺服器,可以將經過代理傳輸的常用文件複製儲存起來。下一個請求同一文件的客戶端就可以享受快取的私有副本所提供的服務了。客戶端從附近的快取下載文件會比從遠端 Web 伺服器下載快得多。
3. 閘道器
HTTP / FTP 閘道器閘道器是一種特殊的伺服器,作為其他伺服器的中間實體使用。通常用於將 HTTP 流量轉換成其他的協議。閘道器接收請求時就好像自己是資源的源伺服器一樣。客戶端可能並不知道自己正在跟一個閘道器進行通訊。
4. 隧道
HTTP/SSL 隧道隧道是會在建立起來之後,就會在兩條連線之間對原始資料進行盲轉發的 HTTP 應用程式。HTTP 隧道通常用來在一條或多條 HTTP 連線上轉發非 HTTP 資料,轉發時不會窺探資料。
HTTP 隧道的一種常見用途就是通過 HTTP 連線承載加密的安全套接字層(SSL)流量,這樣 SSL 流量就可以穿過只允許 Web 流量通過的防火牆了。
5. Agent 代理
自動搜尋引擎“網路蜘蛛”Agent 代理是代表使用者發起 HTTP 請求的客戶端應用程式。所有釋出 Web 請求的應用程式都是 HTTP Agent 代理。
作者:滌生_Woo
連結:https://www.jianshu.com/p/6e9e4156ece3
來源:簡書
著作權歸作者所有。商業轉載請聯絡作者獲得授權,非商業轉載請註明出處。