一萬五千字詳解HTTP協(xié)議

本篇文章篇幅比較長,先來個思維導圖預(yù)覽一下。

一、概述
1.計算機網(wǎng)絡(luò)體系結(jié)構(gòu)分層

2.TCP/IP 通信傳輸流
利用 TCP/IP 協(xié)議族進行網(wǎng)絡(luò)通信時,會通過分層順序與對方進行通信。發(fā)送端從應(yīng)用層往下走,接收端則從鏈路層往上走。如下:

TCP/IP 通信傳輸流
首先作為發(fā)送端的客戶端在應(yīng)用層(HTTP 協(xié)議)發(fā)出一個想看某個 Web 頁面的 HTTP 請求。
接著,為了傳輸方便,在傳輸層(TCP 協(xié)議)把從應(yīng)用層處收到的數(shù)據(jù)(HTTP 請求報文)進行分割,并在各個報文上打上標記序號及端口號后轉(zhuǎn)發(fā)給網(wǎng)絡(luò)層。
在網(wǎng)絡(luò)層(IP 協(xié)議),增加作為通信目的地的 MAC 地址后轉(zhuǎn)發(fā)給鏈路層。這樣一來,發(fā)往網(wǎng)絡(luò)的通信請求就準備齊全了。
接收端的服務(wù)器在鏈路層接收到數(shù)據(jù),按序往上層發(fā)送,一直到應(yīng)用層。當傳輸?shù)綉?yīng)用層,才能算真正接收到由客戶端發(fā)送過來的 HTTP請求。
如下圖所示:

HTTP 請求
在網(wǎng)絡(luò)體系結(jié)構(gòu)中,包含了眾多的網(wǎng)絡(luò)協(xié)議,這篇文章主要圍繞 HTTP 協(xié)議(HTTP/1.1版本)展開。
HTTP協(xié)議(HyperText Transfer Protocol,超文本傳輸協(xié)議)是用于從WWW服務(wù)器傳輸超文本到本地瀏覽器的傳輸協(xié)議。它可以使瀏覽器更加高效,使網(wǎng)絡(luò)傳輸減少。它不僅保證計算機正確快速地傳輸超文本文檔,還確定傳輸文檔中的哪一部分,以及哪部分內(nèi)容首先顯示(如文本先于圖形)等。
HTTP是客戶端瀏覽器或其他程序與Web服務(wù)器之間的應(yīng)用層通信協(xié)議。在Internet上的Web服務(wù)器上存放的都是超文本信息,客戶機需要通過HTTP協(xié)議傳輸所要訪問的超文本信息。HTTP包含命令和傳輸信息,不僅可用于Web訪問,也可以用于其他因特網(wǎng)/內(nèi)聯(lián)網(wǎng)應(yīng)用系統(tǒng)之間的通信,從而實現(xiàn)各類應(yīng)用資源超媒體訪問的集成。
我們在瀏覽器的地址欄里輸入的網(wǎng)站地址叫做URL (Uniform Resource Locator,統(tǒng)一資源定位符)。就像每家每戶都有一個門牌地址一樣,每個網(wǎng)頁也都有一個Internet地址。當你在瀏覽器的地址框中輸入一個URL或是單擊一個超級鏈接時,URL就確定了要瀏覽的地址。瀏覽器通過超文本傳輸協(xié)議(HTTP),將Web服務(wù)器上站點的網(wǎng)頁代碼提取出來,并翻譯成漂亮的網(wǎng)頁。
二、HTTP 工作過程

HTTP通信機制是在一次完整的 HTTP 通信過程中,客戶端與服務(wù)器之間將完成下列7個步驟:
建立 TCP 連接
在HTTP工作開始之前,客戶端首先要通過網(wǎng)絡(luò)與服務(wù)器建立連接,該連接是通過 TCP 來完成的,該協(xié)議與 IP 協(xié)議共同構(gòu)建 Internet,即著名的 TCP/IP 協(xié)議族,因此 Internet 又被稱作是 TCP/IP 網(wǎng)絡(luò)。HTTP 是比 TCP 更高層次的應(yīng)用層協(xié)議,根據(jù)規(guī)則,只有低層協(xié)議建立之后,才能進行高層協(xié)議的連接,因此,首先要建立 TCP 連接,一般 TCP 連接的端口號是80;客戶端向服務(wù)器發(fā)送請求命令
一旦建立了TCP連接,客戶端就會向服務(wù)器發(fā)送請求命令;
例如:GET/sample/hello.jsp HTTP/1.1客戶端發(fā)送請求頭信息
客戶端發(fā)送其請求命令之后,還要以頭信息的形式向服務(wù)器發(fā)送一些別的信息,之后客戶端發(fā)送了一空白行來通知服務(wù)器,它已經(jīng)結(jié)束了該頭信息的發(fā)送;服務(wù)器應(yīng)答
客戶端向服務(wù)器發(fā)出請求后,服務(wù)器會客戶端返回響應(yīng);
例如:HTTP/1.1 200 OK
響應(yīng)的第一部分是協(xié)議的版本號和響應(yīng)狀態(tài)碼服務(wù)器返回響應(yīng)頭信息
正如客戶端會隨同請求發(fā)送關(guān)于自身的信息一樣,服務(wù)器也會隨同響應(yīng)向用戶發(fā)送關(guān)于它自己的數(shù)據(jù)及被請求的文檔;服務(wù)器向客戶端發(fā)送數(shù)據(jù)
服務(wù)器向客戶端發(fā)送頭信息后,它會發(fā)送一個空白行來表示頭信息的發(fā)送到此為結(jié)束,接著,它就以 Content-Type 響應(yīng)頭信息所描述的格式發(fā)送用戶所請求的實際數(shù)據(jù);服務(wù)器關(guān)閉 TCP 連接
一般情況下,一旦服務(wù)器向客戶端返回了請求數(shù)據(jù),它就要關(guān)閉 TCP 連接,然后如果客戶端或者服務(wù)器在其頭信息加入了這行代碼Connection:keep-alive,TCP 連接在發(fā)送后將仍然保持打開狀態(tài),于是,客戶端可以繼續(xù)通過相同的連接發(fā)送請求。保持連接節(jié)省了為每個請求建立新連接所需的時間,還節(jié)約了網(wǎng)絡(luò)帶寬。
三、HTTP 協(xié)議基礎(chǔ)
1.通過請求和響應(yīng)的交換達成通信
應(yīng)用 HTTP 協(xié)議時,必定是一端擔任客戶端角色,另一端擔任服務(wù)器端角色。僅從一條通信線路來說,服務(wù)器端和客服端的角色是確定的。HTTP 協(xié)議規(guī)定,請求從客戶端發(fā)出,最后服務(wù)器端響應(yīng)該請求并返回。換句話說,肯定是先從客戶端開始建立通信的,服務(wù)器端在沒有接收到請求之前不會發(fā)送響應(yīng)。
2.HTTP 是不保存狀態(tài)的協(xié)議
HTTP 是一種無狀態(tài)協(xié)議。協(xié)議自身不對請求和響應(yīng)之間的通信狀態(tài)進行保存。也就是說在 HTTP 這個級別,協(xié)議對于發(fā)送過的請求或響應(yīng)都不做持久化處理。這是為了更快地處理大量事務(wù),確保協(xié)議的可伸縮性,而特意把 HTTP 協(xié)議設(shè)計成如此簡單的。
可是隨著 Web 的不斷發(fā)展,我們的很多業(yè)務(wù)都需要對通信狀態(tài)進行保存。于是我們引入了 Cookie 技術(shù)。有了 Cookie 再用 HTTP 協(xié)議通信,就可以管理狀態(tài)了。
3.使用 Cookie 的狀態(tài)管理
Cookie 技術(shù)通過在請求和響應(yīng)報文中寫入 Cookie 信息來控制客戶端的狀態(tài)。Cookie 會根據(jù)從服務(wù)器端發(fā)送的響應(yīng)報文內(nèi)的一個叫做 Set-Cookie 的首部字段信息,通知客戶端保存Cookie。當下次客戶端再往該服務(wù)器發(fā)送請求時,客戶端會自動在請求報文中加入 Cookie 值后發(fā)送出去。服務(wù)器端發(fā)現(xiàn)客戶端發(fā)送過來的 Cookie 后,會去檢查究竟是從哪一個客戶端發(fā)來的連接請求,然后對比服務(wù)器上的記錄,最后得到之前的狀態(tài)信息。

4.請求 URI 定位資源
HTTP 協(xié)議使用 URI 定位互聯(lián)網(wǎng)上的資源。正是因為 URI 的特定功能,在互聯(lián)網(wǎng)上任意位置的資源都能訪問到。
5.告知服務(wù)器意圖的 HTTP 方法(HTTP/1.1)

6.持久連接
HTTP 協(xié)議的初始版本中,每進行一個 HTTP 通信都要斷開一次 TCP 連接。比如使用瀏覽器瀏覽一個包含多張圖片的 HTML 頁面時,在發(fā)送請求訪問 HTML 頁面資源的同時,也會請求該 HTML 頁面里包含的其他資源。因此,每次的請求都會造成無畏的 TCP 連接建立和斷開,增加通信量的開銷。
為了解決上述 TCP 連接的問題,HTTP/1.1 和部分 HTTP/1.0 想出了持久連接的方法。其特點是,只要任意一端沒有明確提出斷開連接,則保持 TCP 連接狀態(tài)。旨在建立一次 TCP 連接后進行多次請求和響應(yīng)的交互。在 HTTP/1.1 中,所有的連接默認都是持久連接。
7.管線化
持久連接使得多數(shù)請求以管線化方式發(fā)送成為可能。以前發(fā)送請求后需等待并接收到響應(yīng),才能發(fā)送下一個請求。管線化技術(shù)出現(xiàn)后,不用等待亦可發(fā)送下一個請求。這樣就能做到同時并行發(fā)送多個請求,而不需要一個接一個地等待響應(yīng)了。
比如,當請求一個包含多張圖片的 HTML 頁面時,與挨個連接相比,用持久連接可以讓請求更快結(jié)束。而管線化技術(shù)要比持久連接速度更快。請求數(shù)越多,時間差就越明顯。
四、HTTP 協(xié)議報文結(jié)構(gòu)
1.HTTP 報文
用于 HTTP 協(xié)議交互的信息被稱為 HTTP 報文。請求端(客戶端)的 HTTP 報文叫做請求報文;響應(yīng)端(服務(wù)器端)的叫做響應(yīng)報文。HTTP 報文本身是由多行(用 CR+LF 作換行符)數(shù)據(jù)構(gòu)成的字符串文本。
2.HTTP 報文結(jié)構(gòu)
HTTP 報文大致可分為報文首部和報文主體兩部分。兩者由最初出現(xiàn)的空行(CR+LF)來劃分。通常,并不一定有報文主體。如下:


2.1請求報文結(jié)構(gòu)

請求報文的首部內(nèi)容由以下數(shù)據(jù)組成:
請求行 —— 包含用于請求的方法、請求 URI 和 HTTP 版本。
首部字段 —— 包含表示請求的各種條件和屬性的各類首部。(通用首部、請求首部、實體首部以及RFC里未定義的首部如 Cookie 等)
請求報文的示例,如下:

2.2響應(yīng)報文結(jié)構(gòu)

響應(yīng)報文的首部內(nèi)容由以下數(shù)據(jù)組成:
狀態(tài)行 —— 包含表明響應(yīng)結(jié)果的狀態(tài)碼、原因短語和 HTTP 版本。
首部字段 —— 包含表示請求的各種條件和屬性的各類首部。(通用首部、響應(yīng)首部、實體首部以及RFC里未定義的首部如 Cookie 等)
響應(yīng)報文的示例,如下:

五、HTTP 報文首部之請求行、狀態(tài)行
1.請求行
舉個栗子,下面是一個 HTTP 請求的報文:
GET /index.htm HTTP/1.1Host: sample.com
其中,下面的這行就是請求行:
GET /index.htm HTTP/1.1開頭的 GET 表示請求訪問服務(wù)器的類型,稱為方法;
隨后的字符串
/index.htm指明了請求訪問的資源對象,也叫做請求 URI;最后的
HTTP/1.1,即 HTTP 的版本號,用來提示客戶端使用的 HTTP 協(xié)議功能。
綜合來看,大意是請求訪問某臺 HTTP 服務(wù)器上的 /index.htm 頁面資源。
2.狀態(tài)行
同樣舉個栗子,下面是一個 HTTP 響應(yīng)的報文:
HTTP/1.1 200 OKDate: Mon, 10 Jul 2017 15:50:06 GMTContent-Length: 256Content-Type: text/html<html>...
其中,下面的這行就是狀態(tài)行,
HTTP/1.1 200 OK開頭的
HTTP/1.1表示服務(wù)器對應(yīng)的 HTTP 版本;緊挨著的
200 OK表示請求的處理結(jié)果的狀態(tài)碼和原因短語。
六、HTTP 報文首部之首部字段(重點分析)
1.首部字段概述
先來回顧一下首部字段在報文的位置,HTTP 報文包含報文首部和報文主體,報文首部包含請求行(或狀態(tài)行)和首部字段。
在報文眾多的字段當中,HTTP 首部字段包含的信息最為豐富。首部字段同時存在于請求和響應(yīng)報文內(nèi),并涵蓋 HTTP 報文相關(guān)的內(nèi)容信息。使用首部字段是為了給客服端和服務(wù)器端提供報文主體大小、所使用的語言、認證信息等內(nèi)容。
2.首部字段結(jié)構(gòu)
HTTP 首部字段是由首部字段名和字段值構(gòu)成的,中間用冒號“:”分隔。
另外,字段值對應(yīng)單個 HTTP 首部字段可以有多個值。
當 HTTP 報文首部中出現(xiàn)了兩個或以上具有相同首部字段名的首部字段時,這種情況在規(guī)范內(nèi)尚未明確,根據(jù)瀏覽器內(nèi)部處理邏輯的不同,優(yōu)先處理的順序可能不同,結(jié)果可能并不一致。
| 首部字段名 | 冒號 | 字段值 |
|---|---|---|
| Content-Type | : | text/html |
| Keep-Alive | : | timeout=30, max=120 |
3.首部字段類型
首部字段根據(jù)實際用途被分為以下4種類型:
| 類型 | 描述 |
|---|---|
| 通用首部字段 | 請求報文和響應(yīng)報文兩方都會使用的首部 |
| 請求首部字段 | 從客戶端向服務(wù)器端發(fā)送請求報文時使用的首部。補充了請求的附加內(nèi)容、客戶端信息、響應(yīng)內(nèi)容相關(guān)優(yōu)先級等信息 |
| 響應(yīng)首部字段 | 從服務(wù)器端向客戶端返回響應(yīng)報文時使用的首部。補充了響應(yīng)的附加內(nèi)容,也會要求客戶端附加額外的內(nèi)容信息。 |
| 實體首部字段 | 針對請求報文和響應(yīng)報文的實體部分使用的首部。補充了資源內(nèi)容更新時間等與實體有關(guān)的的信息。 |
4.通用首部字段(HTTP/1.1)
| 首部字段名 | 說明 |
|---|---|
| Cache-Control | 控制緩存的行為 |
| Connection | 逐挑首部、連接的管理 |
| Date | 創(chuàng)建報文的日期時間 |
| Pragma | 報文指令 |
| Trailer | 報文末端的首部一覽 |
| Transfer-Encoding | 指定報文主體的傳輸編碼方式 |
| Upgrade | 升級為其他協(xié)議 |
| Via | 代理服務(wù)器的相關(guān)信息 |
| Warning | 錯誤通知 |
4.1 Cache-Control
通過指定首部字段 Cache-Control 的指令,就能操作緩存的工作機制。
4.1.1 可用的指令一覽
可用的指令按請求和響應(yīng)分類如下:
緩存請求指令
| 指令 | 參數(shù) | 說明 |
|---|---|---|
| no-cache | 無 | 強制向服務(wù)器再次驗證 |
| no-store | 無 | 不緩存請求或響應(yīng)的任何內(nèi)容 |
| max-age = [秒] | 必需 | 響應(yīng)的最大Age值 |
| max-stale( =[秒]) | 可省略 | 接收已過期的響應(yīng) |
| min-fresh = [秒] | 必需 | 期望在指定時間內(nèi)的響應(yīng)仍有效 |
| no-transform | 無 | 代理不可更改媒體類型 |
| only-if-cached | 無 | 從緩存獲取資源 |
| cache-extension | - | 新指令標記(token) |
緩存響應(yīng)指令
| 指令 | 參數(shù) | 說明 |
|---|---|---|
| public | 無 | 可向任意方提供響應(yīng)的緩存 |
| private | 可省略 | 僅向特定用戶返回響應(yīng) |
| no-cache | 可省略 | 緩存前必須先確認其有效性 |
| no-store | 無 | 不緩存請求或響應(yīng)的任何內(nèi)容 |
| no-transform | 無 | 代理不可更改媒體類型 |
| must-revalidate | 無 | 可緩存但必須再向源服務(wù)器進行確認 |
| proxy-revalidate | 無 | 要求中間緩存服務(wù)器對緩存的響應(yīng)有效性再進行確認 |
| max-age = [秒] | 必需 | 響應(yīng)的最大Age值 |
| s-maxage = [秒] | 必需 | 公共緩存服務(wù)器響應(yīng)的最大Age值 |
| cache-extension | - | 新指令標記(token) |
4.1.2 表示能否緩存的指令
public 指令Cache-Control: public
當指定使用 public 指令時,則明確表明其他用戶也可利用緩存。
private 指令Cache-Control: private
當指定 private 指令后,響應(yīng)只以特定的用戶作為對象,這與 public 指令的行為相反。緩存服務(wù)器會對該特定用戶提供資源緩存的服務(wù),對于其他用戶發(fā)送過來的請求,代理服務(wù)器則不會返回緩存。
no-cache 指令Cache-Control: no-cache
使用 no-cache 指令是為了防止從緩存中返回過期的資源。
客戶端發(fā)送的請求中如果包含 no-cache 指令,則表示客戶端將不會接收緩存過的響應(yīng)。于是,“中間”的緩存服務(wù)器必須把客戶端請求轉(zhuǎn)發(fā)給源服務(wù)器。
如果服務(wù)器中返回的響應(yīng)包含 no-cache 指令,那么緩存服務(wù)器不能對資源進行緩存。源服務(wù)器以后也將不再對緩存服務(wù)器請求中提出的資源有效性進行確認,且禁止其對響應(yīng)資源進行緩存操作。
Cache-Control: no-cache=Location
由服務(wù)器返回的響應(yīng)中,若報文首部字段 Cache-Control 中對 no-cache 字段名具體指定參數(shù)值,那么客戶端在接收到這個被指定參數(shù)值的首部字段對應(yīng)的響應(yīng)報文后,就不能使用緩存。換言之,無參數(shù)值的首部字段可以使用緩存。只能在響應(yīng)指令中指定該參數(shù)。
no-store 指令Cache-Control: no-store
當使用 no-store 指令時,暗示請求(和對應(yīng)的響應(yīng))或響應(yīng)中包含機密信息。因此,該指令規(guī)定緩存不能在本地存儲請求或響應(yīng)的任一部分。
注意:no-cache 指令代表不緩存過期的指令,緩存會向源服務(wù)器進行有效期確認后處理資源;no-store 指令才是真正的不進行緩存。
4.1.3 指定緩存期限和認證的指令
s-maxage 指令Cache-Control: s-maxage=604800(單位:秒)
s-maxage 指令的功能和 max-age 指令的相同,它們的不同點是 s-maxage 指令只適用于供多位用戶使用的公共緩存服務(wù)器(一般指代理)。也就是說,對于向同一用戶重復返回響應(yīng)的服務(wù)器來說,這個指令沒有任何作用。
另外,當使用 s-maxage 指令后,則直接忽略對 Expires 首部字段及 max-age 指令的處理。
max-age 指令Cache-Control: max-age=604800(單位:秒)
當客戶端發(fā)送的請求中包含 max-age 指令時,如果判定緩存資源的緩存時間數(shù)值比指定的時間更小,那么客戶端就接收緩存的資源。另外,當指定 max-age 的值為0,那么緩存服務(wù)器通常需要將請求轉(zhuǎn)發(fā)給源服務(wù)器。
當服務(wù)器返回的響應(yīng)中包含 max-age 指令時,緩存服務(wù)器將不對資源的有效性再作確認,而 max-age 數(shù)值代表資源保存為緩存的最長時間。
應(yīng)用 HTTP/1.1 版本的緩存服務(wù)器遇到同時存在 Expires 首部字段的情況時,會優(yōu)先處理 max-age 指令,并忽略掉 Expires 首部字段;而 HTTP/1.0 版本的緩存服務(wù)器則相反。
min-fresh 指令Cache-Control: min-fresh=60(單位:秒)
min-fresh 指令要求緩存服務(wù)器返回至少還未過指定時間的緩存資源。
max-stale 指令Cache-Control: max-stale=3600(單位:秒)
使用 max-stale 可指示緩存資源,即使過期也照常接收。
如果指令未指定參數(shù)值,那么無論經(jīng)過多久,客戶端都會接收響應(yīng);如果指定了具體參數(shù)值,那么即使過期,只要仍處于 max-stale 指定的時間內(nèi),仍舊會被客戶端接收。
only-if-cached 指令Cache-Control: only-if-cached
表示客戶端僅在緩存服務(wù)器本地緩存目標資源的情況下才會要求其返回。換言之,該指令要求緩存服務(wù)器不重新加載響應(yīng),也不會再次確認資源的有效性。
must-revalidate 指令Cache-Control: must-revalidate
使用 must-revalidate 指令,代理會向源服務(wù)器再次驗證即將返回的響應(yīng)緩存目前是否仍有效。另外,使用 must-revalidate 指令會忽略請求的 max-stale 指令。
proxy-revalidate 指令Cache-Control: proxy-revalidate
proxy-revalidate 指令要求所有的緩存服務(wù)器在接收到客戶端帶有該指令的請求返回響應(yīng)之前,必須再次驗證緩存的有效性。
no-transform 指令Cache-Control: no-transform
使用 no-transform 指令規(guī)定無論是在請求還是響應(yīng)中,緩存都不能改變實體主體的媒體類型。這樣做可防止緩存或代理壓縮圖片等類似操作。
4.1.4 Cache-Control 擴展
Cache-Control: private, community="UCI"
通過 cache-extension 標記(token),可以擴展 Cache-Control 首部字段內(nèi)的指令。上述 community 指令即擴展的指令,如果緩存服務(wù)器不能理解這個新指令,就會直接忽略掉。
4.2 Connection
Connection 首部字段具備以下兩個作用:
控制不再轉(zhuǎn)發(fā)的首部字段Connection: Upgrade
在客戶端發(fā)送請求和服務(wù)器返回響應(yīng)中,使用 Connection 首部字段,可控制不再轉(zhuǎn)發(fā)給代理的首部字段,即刪除后再轉(zhuǎn)發(fā)(即Hop-by-hop首部)。
管理持久連接Connection: close
HTTP/1.1 版本的默認連接都是持久連接。當服務(wù)器端想明確斷開連接時,則指定 Connection 首部字段的值為 close。Connection: Keep-Alive
HTTP/1.1 之前的 HTTP 版本的默認連接都是非持久連接。為此,如果想在舊版本的 HTTP 協(xié)議上維持持續(xù)連接,則需要指定 Connection 首部字段的值為 Keep-Alive。
4.3 Date
表明創(chuàng)建 HTTP 報文的日期和時間。Date: Mon, 10 Jul 2017 15:50:06 GMT
HTTP/1.1 協(xié)議使用在 RFC1123 中規(guī)定的日期時間的格式。
4.4 Pragma
Pragma 首部字段是 HTTP/1.1 版本之前的歷史遺留字段,僅作為與 HTTP/1.0 的向后兼容而定義。Pragma: no-cache
該首部字段屬于通用首部字段,但只用在客戶端發(fā)送的請求中,要求所有的中間服務(wù)器不返回緩存的資源。
所有的中間服務(wù)器如果都能以 HTTP/1.1 為基準,那直接采用
Cache-Control: no-cache指定緩存的處理方式最為理想。但是要整體掌握所有中間服務(wù)器使用的 HTTP 協(xié)議版本卻是不現(xiàn)實的,所以,發(fā)送的請求會同時包含下面兩個首部字段:
Cache-Control: no-cache
Pragma: no-cache
4.5 Trailer
Trailer: Expires
首部字段 Trailer 會事先說明在報文主體后記錄了哪些首部字段??蓱?yīng)用在 HTTP/1.1 版本分塊傳輸編碼時。
4.6 Transfer-Encoding
Transfer-Encoding: chunked
規(guī)定了傳輸報文主體時采用的編碼方式。
HTTP/1.1 的傳輸編碼方式僅對分塊傳輸編碼有效。
4.7 Upgrade
Upgrade: TSL/1.0
用于檢測 HTTP 協(xié)議及其他協(xié)議是否可使用更高的版本進行通信,其參數(shù)值可以用來指定一個完全不同的通信協(xié)議。
4.8 Via
Via: 1.1 a1.sample.com(Squid/2.7)
為了追蹤客戶端和服務(wù)器端之間的請求和響應(yīng)報文的傳輸路徑。
報文經(jīng)過代理或網(wǎng)關(guān)時,會現(xiàn)在首部字段 Via 中附加該服務(wù)器的信息,然后再進行轉(zhuǎn)發(fā)。
首部字段 Via 不僅用于追蹤報文的轉(zhuǎn)發(fā),還可避免請求回環(huán)的發(fā)生。
4.9 Warning
該首部字段通常會告知用戶一些與緩存相關(guān)的問題的警告。
Warning 首部字段的格式如下:Warning:[警告碼][警告的主機:端口號] "[警告內(nèi)容]"([日期時間])
最后的日期時間可省略。
HTTP/1.1 中定義了7種警告,警告碼對應(yīng)的警告內(nèi)容僅推薦參考,另外,警告碼具備擴展性,今后有可能追加新的警告碼。
| 警告碼 | 警告內(nèi)容 | 說明 |
|---|---|---|
| 110 | Response is stale(響應(yīng)已過期) | 代理返回已過期的資源 |
| 111 | Revalidation failed(再驗證失敗) | 代理再驗證資源有效性時失敗(服務(wù)器無法到達等原因) |
| 112 | Disconnection operation(斷開連接操作) | 代理與互聯(lián)網(wǎng)連接被故意切斷 |
| 113 | Heuristic expiration(試探性過期) | 響應(yīng)的試用期超過24小時(有效緩存的設(shè)定時間大于24小時的情況下) |
| 199 | Miscellaneous warning(雜項警告) | 任意的警告內(nèi)容 |
| 214 | Transformation applied(使用了轉(zhuǎn)換) | 代理對內(nèi)容編碼或媒體類型等執(zhí)行了某些處理時 |
| 299 | Miscellaneous persistent warning(持久雜項警告) | 任意的警告內(nèi)容 |
5. 請求首部字段(HTTP/1.1)
| 首部字段名 | 說明 |
|---|---|
| Accept | 用戶代理可處理的媒體類型 |
| Accept-Charset | 優(yōu)先的字符集 |
| Accept-Encoding | 優(yōu)先的內(nèi)容編碼 |
| Accept-Language | 優(yōu)先的語言(自然語言) |
| Authorization | Web認證信息 |
| Expect | 期待服務(wù)器的特定行為 |
| From | 用戶的電子郵箱地址 |
| Host | 請求資源所在服務(wù)器 |
| If-Match | 比較實體標記(ETag) |
| If-Modified-Since | 比較資源的更新時間 |
| If-None-Match | 比較實體標記(與 If-Macth 相反) |
| If-Range | 資源未更新時發(fā)送實體 Byte 的范圍請求 |
| If-Unmodified-Since | 比較資源的更新時間(與 If-Modified-Since 相反) |
| Max-Forwards | 最大傳輸逐跳數(shù) |
| Proxy-Authorization | 代理服務(wù)器要求客戶端的認證信息 |
| Range | 實體的字節(jié)范圍請求 |
| Referer | 對請求中 URI 的原始獲取方 |
| TE | 傳輸編碼的優(yōu)先級 |
| User-Agent | HTTP 客戶端程序的信息 |
5.1 Accept
Accept: text/html, application/xhtml+xml, application/xml; q=0.5
Accept 首部字段可通知服務(wù)器,用戶代理能夠處理的媒體類型及媒體類型的相對優(yōu)先級。可使用 type/subtype 這種形式,一次指定多種媒體類型。
若想要給顯示的媒體類型增加優(yōu)先級,則使用
q=[數(shù)值]來表示權(quán)重值,用分號(;)進行分隔。權(quán)重值的范圍 0~1(可精確到小數(shù)點后三位),且 1 為最大值。不指定權(quán)重值時,默認為 1。
5.2 Accept-Charset
Accept-Charset: iso-8859-5, unicode-1-1; q=0.8
Accept-Charset 首部字段可用來通知服務(wù)器用戶代理支持的字符集及字符集的相對優(yōu)先順序。另外,可一次性指定多種字符集。同樣使用 q=[數(shù)值] 來表示相對優(yōu)先級。
5.3 Accept-Encoding
Accept-Encoding: gzip, deflate
Accept-Encoding 首部字段用來告知服務(wù)器用戶代理支持的內(nèi)容編碼及內(nèi)容編碼的優(yōu)先順序,并可一次性指定多種內(nèi)容編碼。同樣使用 q=[數(shù)值] 來表示相對優(yōu)先級。也可使用星號(*)作為通配符,指定任意的編碼格式。
5.4 Accept-Language
Accept-Lanuage: zh-cn,zh;q=0.7,en=us,en;q=0.3
告知服務(wù)器用戶代理能夠處理的自然語言集(指中文或英文等),以及自然語言集的相對優(yōu)先級,可一次性指定多種自然語言集。同樣使用 q=[數(shù)值] 來表示相對優(yōu)先級。
5.5 Authorization
Authorization: Basic ldfKDHKfkDdasSAEdasd==
告知服務(wù)器用戶代理的認證信息(證書值)。通常,想要通過服務(wù)器認證的用戶代理會在接收到返回的 401 狀態(tài)碼響應(yīng)后,把首部字段 Authorization 加入請求中。共用緩存在接收到含有 Authorization 首部字段的請求時的操作處理會略有差異。
5.6 Expect
Expect: 100-continue
告知服務(wù)器客戶端期望出現(xiàn)的某種特定行為。
5.7 From
From: [email protected]
告知服務(wù)器使用用戶代理的電子郵件地址。
5.8 Host
Host: www.jianshu.com
告知服務(wù)器,請求的資源所處的互聯(lián)網(wǎng)主機和端口號。
Host 首部字段是 HTTP/1.1 規(guī)范內(nèi)唯一一個必須被包含在請求內(nèi)的首部字段。
若服務(wù)器未設(shè)定主機名,那直接發(fā)送一個空值即可
Host:。
5.9 If-Match
形如 If-xxx 這種樣式的請求首部字段,都可稱為條件請求。服務(wù)器接收到附帶條件的請求后,只有判斷指定條件為真時,才會執(zhí)行請求。
If-Match: "123456"
首部字段 If-Match,屬附帶條件之一,它會告知服務(wù)器匹配資源所用的實體標記(ETag)值。這時的服務(wù)器無法使用弱 ETag 值。
服務(wù)器會比對 If-Match 的字段值和資源的 ETag 值,僅當兩者一致時,才會執(zhí)行請求。反之,則返回狀態(tài)碼
412 Precondition Failed的響應(yīng)。還可以使用星號(*)指定 If-Match 的字段值。針對這種情況,服務(wù)器將會忽略 ETag 的值,只要資源存在就處理請求。
5.10 If-Modified-Since
If-Modified-Since: Mon, 10 Jul 2017 15:50:06 GMT
首部字段 If-Modified-Since,屬附帶條件之一,用于確認代理或客戶端擁有的本地資源的有效性。
它會告知服務(wù)器若 If-Modified-Since 字段值早于資源的更新時間,則希望能處理該請求。而在指定 If-Modified-Since 字段值的日期時間之后,如果請求的資源都沒有過更新,則返回狀態(tài)碼
304 Not Modified的響應(yīng)。
5.11 If-None-Match
If-None-Match: "123456"
首部字段 If-None-Match 屬于附帶條件之一。它和首部字段 If-Match 作用相反。用于指定 If-None-Match 字段值的實體標記(ETag)值與請求資源的 ETag 不一致時,它就告知服務(wù)器處理該請求。
5.12 If-Range
If-Range: "123456"
首部字段 If-Range 屬于附帶條件之一。它告知服務(wù)器若指定的 If-Range 字段值(ETag 值或者時間)和請求資源的 ETag 值或時間相一致時,則作為范圍請求處理。反之,則返回全體資源。
下面我們思考一下不使用首部字段 If-Range 發(fā)送請求的情況。服務(wù)器端的資源如果更新,那客戶端持有資源中的一部分也會隨之無效,當然,范圍請求作為前提是無效的。這時,服務(wù)器會暫且以狀態(tài)碼
412 Precondition Failed作為響應(yīng)返回,其目的是催促客戶端再次發(fā)送請求。這樣一來,與使用首部字段 If-Range 比起來,就需要花費兩倍的功夫。
5.13 If-Unmodified-Since
If-Unmodified-Since: Mon, 10 Jul 2017 15:50:06 GMT
首部字段 If-Unmodified-Since 和首部字段 If-Modified-Since 的作用相反。它的作用的是告知服務(wù)器,指定的請求資源只有在字段值內(nèi)指定的日期時間之后,未發(fā)生更新的情況下,才能處理請求。如果在指定日期時間后發(fā)生了更新,則以狀態(tài)碼 412 Precondition Failed 作為響應(yīng)返回。
5.14 Max-Forwards
Max-Forwards: 10
通過 TRACE 方法或 OPTIONS 方法,發(fā)送包含首部字段 Max-Forwards 的請求時,該字段以十進制整數(shù)形式指定可經(jīng)過的服務(wù)器最大數(shù)目。服務(wù)器在往下一個服務(wù)器轉(zhuǎn)發(fā)請求之前,Max-Forwards 的值減 1 后重新賦值。當服務(wù)器接收到 Max-Forwards 值為 0 的請求時,則不再進行轉(zhuǎn)發(fā),而是直接返回響應(yīng)。
5.15 Proxy-Authorization
Proxy-Authorization: Basic dGlwOjkpNLAGfFY5
接收到從代理服務(wù)器發(fā)來的認證質(zhì)詢時,客戶端會發(fā)送包含首部字段 Proxy-Authorization 的請求,以告知服務(wù)器認證所需要的信息。
這個行為是與客戶端和服務(wù)器之間的 HTTP 訪問認證相類似的,不同之處在于,認證行為發(fā)生在客戶端與代理之間。
5.16 Range
Range: bytes=5001-10000
對于只需獲取部分資源的范圍請求,包含首部字段 Range 即可告知服務(wù)器資源的指定范圍。
接收到附帶 Range 首部字段請求的服務(wù)器,會在處理請求之后返回狀態(tài)碼為
206 Partial Content的響應(yīng)。無法處理該范圍請求時,則會返回狀態(tài)碼200 OK的響應(yīng)及全部資源。
5.17 Referer
Referer: http://www.sample.com/index.html
首部字段 Referer 會告知服務(wù)器請求的原始資源的 URI。
5.18 TE
TE: gzip, deflate; q=0.5
首部字段 TE 會告知服務(wù)器客戶端能夠處理響應(yīng)的傳輸編碼方式及相對優(yōu)先級。它和首部字段 Accept-Encoding 的功能很相像,但是用于傳輸編碼。
首部字段 TE 除指定傳輸編碼之外,還可以指定伴隨 trailer 字段的分塊傳輸編碼的方式。應(yīng)用后者時,只需把 trailers 賦值給該字段值。
TE: trailers
5.19 User-Agent
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:13.0) Gecko/20100101
首部字段 User-Agent 會將創(chuàng)建請求的瀏覽器和用戶代理名稱等信息傳達給服務(wù)器。
由網(wǎng)絡(luò)爬蟲發(fā)起請求時,有可能會在字段內(nèi)添加爬蟲作者的電子郵件地址。此外,如果請求經(jīng)過代理,那么中間也很可能被添加上代理服務(wù)器的名稱。
6. 響應(yīng)首部字段(HTTP/1.1)
| 首部字段名 | 說明 |
|---|---|
| Accept-Ranges | 是否接受字節(jié)范圍請求 |
| Age | 推算資源創(chuàng)建經(jīng)過時間 |
| ETag | 資源的匹配信息 |
| Location | 令客戶端重定向至指定 URI |
| Proxy-Authenticate | 代理服務(wù)器對客戶端的認證信息 |
| Retry-After | 對再次發(fā)起請求的時機要求 |
| Server | HTTP 服務(wù)器的安裝信息 |
| Vary | 代理服務(wù)器緩存的管理信息 |
| WWW-Authenticate | 服務(wù)器對客戶端的認證信息 |
6.1 Accept-Ranges
Accept-Ranges: bytes
首部字段 Accept-Ranges 是用來告知客戶端服務(wù)器是否能處理范圍請求,以指定獲取服務(wù)器端某個部分的資源。
可指定的字段值有兩種,可處理范圍請求時指定其為 bytes,反之則指定其為 none。
6.2 Age
Age: 1200
首部字段 Age 能告知客戶端,源服務(wù)器在多久前創(chuàng)建了響應(yīng)。字段值的單位為秒。
若創(chuàng)建該響應(yīng)的服務(wù)器是緩存服務(wù)器,Age 值是指緩存后的響應(yīng)再次發(fā)起認證到認證完成的時間值。代理創(chuàng)建響應(yīng)時必須加上首部字段 Age。
6.3 ETag
ETag: "usagi-1234"
首部字段 ETag 能告知客戶端實體標識。它是一種可將資源以字符串形式做唯一性標識的方式。服務(wù)器會為每份資源分配對應(yīng)的 ETag 值。
另外,當資源更新時,ETag 值也需要更新。生成 ETag 值時,并沒有統(tǒng)一的算法規(guī)則,而僅僅是由服務(wù)器來分配。
ETag 中有強 ETag 值和弱 ETag 值之分。強 ETag 值,不論實體發(fā)生多么細微的變化都會改變其值;弱 ETag 值只用于提示資源是否相同。只有資源發(fā)生了根本改變,產(chǎn)生差異時才會改變 ETag 值。這時,會在字段值最開始處附加 W/:
ETag: W/"usagi-1234"。
6.4 Location
Location: http://www.sample.com/sample.html
使用首部字段 Location 可以將響應(yīng)接收方引導至某個與請求 URI 位置不同的資源。
基本上,該字段會配合 3xx :Redirection 的響應(yīng),提供重定向的 URI。
幾乎所有的瀏覽器在接收到包含首部字段 Location 的響應(yīng)后,都會強制性地嘗試對已提示的重定向資源的訪問。
6.5 Proxy-Authenticate
Proxy-Authenticate: Basic realm="Usagidesign Auth"
首部字段 Proxy-Authenticate 會把由代理服務(wù)器所要求的認證信息發(fā)送給客戶端。
它與客戶端和服務(wù)器之間的 HTTP 訪問認證的行為相似,不同之處在于其認證行為是在客戶端與代理之間進行的。
6.6 Retry-After
Retry-After: 180
首部字段 Retry-After 告知客戶端應(yīng)該在多久之后再次發(fā)送請求。主要配合狀態(tài)碼
503 Service Unavailable響應(yīng),或 3xx Redirect 響應(yīng)一起使用。字段值可以指定為具體的日期時間(Mon, 10 Jul 2017 15:50:06 GMT 等格式),也可以是創(chuàng)建響應(yīng)后的秒數(shù)。
6.7 Server
Server: Apache/2.2.6 (Unix) PHP/5.2.5
首部字段 Server 告知客戶端當前服務(wù)器上安裝的 HTTP 服務(wù)器應(yīng)用程序的信息。不單單會標出服務(wù)器上的軟件應(yīng)用名稱,還有可能包括版本號和安裝時啟用的可選項。
6.8 Vary
Vary: Accept-Language
首部字段 Vary 可對緩存進行控制。源服務(wù)器會向代理服務(wù)器傳達關(guān)于本地緩存使用方法的命令。
從代理服務(wù)器接收到源服務(wù)器返回包含 Vary 指定項的響應(yīng)之后,若再要進行緩存,僅對請求中含有相同 Vary 指定首部字段的請求返回緩存。即使對相同資源發(fā)起請求,但由于 Vary 指定的首部字段不相同,因此必須要從源服務(wù)器重新獲取資源。
6.9 WWW-Authenticate
WWW-Authenticate: Basic realm="Usagidesign Auth"
首部字段 WWW-Authenticate 用于 HTTP 訪問認證。它會告知客戶端適用于訪問請求 URI 所指定資源的認證方案(Basic 或是 Digest)和帶參數(shù)提示的質(zhì)詢(challenge)。
7. 實體首部字段(HTTP/1.1)
| 首部字段名 | 說明 |
|---|---|
| Allow | 資源可支持的 HTTP 方法 |
| Content-Encoding | 實體主體適用的編碼方式 |
| Content-Language | 實體主體的自然語言 |
| Content-Length | 實體主體的大小(單位:字節(jié)) |
| Content-Location | 替代對應(yīng)資源的 URI |
| Content-MD5 | 實體主體的報文摘要 |
| Content-Range | 實體主體的位置范圍 |
| Content-Type | 實體主體的媒體類型 |
| Expires | 實體主體過期的日期時間 |
| Last-Modified | 資源的最后修改日期時間 |
7.1 Allow
Allow: GET, HEAD
首部字段 Allow 用于通知客戶端能夠支持 Request-URI 指定資源的所有 HTTP 方法。
當服務(wù)器接收到不支持的 HTTP 方法時,會以狀態(tài)碼
405 Method Not Allowed作為響應(yīng)返回。與此同時,還會把所有能支持的 HTTP 方法寫入首部字段 Allow 后返回。
7.2 Content-Encoding
Content-Encoding: gzip
首部字段 Content-Encoding 會告知客戶端服務(wù)器對實體的主體部分選用的內(nèi)容編碼方式。內(nèi)容編碼是指在不丟失實體信息的前提下所進行的壓縮。
主要采用這 4 種內(nèi)容編碼的方式(gzip、compress、deflate、identity)。
7.3 Content-Language
Content-Language: zh-CN
首部字段 Content-Language 會告知客戶端,實體主體使用的自然語言(指中文或英文等語言)。
7.4 Content-Length
Content-Length: 15000
首部字段 Content-Length 表明了實體主體部分的大?。▎挝皇亲止?jié))。對實體主體進行內(nèi)容編碼傳輸時,不能再使用 Content-Length首部字段。
7.5 Content-Location
Content-Location: http://www.sample.com/index.html
首部字段 Content-Location 給出與報文主體部分相對應(yīng)的 URI。和首部字段 Location 不同,Content-Location 表示的是報文主體返回資源對應(yīng)的 URI。
7.6 Content-MD5
Content-MD5: OGFkZDUwNGVhNGY3N2MxMDIwZmQ4NTBmY2IyTY==
首部字段 Content-MD5 是一串由 MD5 算法生成的值,其目的在于檢查報文主體在傳輸過程中是否保持完整,以及確認傳輸?shù)竭_。
7.7 Content-Range
Content-Range: bytes 5001-10000/10000
針對范圍請求,返回響應(yīng)時使用的首部字段 Content-Range,能告知客戶端作為響應(yīng)返回的實體的哪個部分符合范圍請求。字段值以字節(jié)為單位,表示當前發(fā)送部分及整個實體大小。
7.8 Content-Type
Content-Type: text/html; charset=UTF-8
首部字段 Content-Type 說明了實體主體內(nèi)對象的媒體類型。和首部字段 Accept 一樣,字段值用 type/subtype 形式賦值。參數(shù) charset 使用 iso-8859-1 或 euc-jp 等字符集進行賦值。
7.9 Expires
Expires: Mon, 10 Jul 2017 15:50:06 GMT
首部字段 Expires 會將資源失效的日期告知客戶端。
緩存服務(wù)器在接收到含有首部字段 Expires 的響應(yīng)后,會以緩存來應(yīng)答請求,在 Expires 字段值指定的時間之前,響應(yīng)的副本會一直被保存。當超過指定的時間后,緩存服務(wù)器在請求發(fā)送過來時,會轉(zhuǎn)向源服務(wù)器請求資源。
源服務(wù)器不希望緩存服務(wù)器對資源緩存時,最好在 Expires 字段內(nèi)寫入與首部字段 Date 相同的時間值。
7.10 Last-Modified
Last-Modified: Mon, 10 Jul 2017 15:50:06 GMT
首部字段 Last-Modified 指明資源最終修改的時間。一般來說,這個值就是 Request-URI 指定資源被修改的時間。但類似使用 CGI 腳本進行動態(tài)數(shù)據(jù)處理時,該值有可能會變成數(shù)據(jù)最終修改時的時間。
8. 為 Cookie 服務(wù)的首部字段
| 首部字段名 | 說明 | 首部類型 |
|---|---|---|
| Set-Cookie | 開始狀態(tài)管理所使用的 Cookie 信息 | 響應(yīng)首部字段 |
| Cookie | 服務(wù)器接收到的 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 的有效期(若不明確指定則默認為瀏覽器關(guān)閉前為止) |
| path=PATH | 將服務(wù)器上的文件目錄作為Cookie的適用對象(若不指定則默認為文檔所在的文件目錄) |
| domain=域名 | 作為 Cookie 適用對象的域名 (若不指定則默認為創(chuàng)建 Cookie的服務(wù)器的域名) |
| Secure | 僅在 HTTPS 安全通信時才會發(fā)送 Cookie |
| HttpOnly | 加以限制,使 Cookie 不能被 JavaScript 腳本訪問 |
8.1.1 expires 屬性
Cookie 的 expires 屬性指定瀏覽器可發(fā)送 Cookie 的有效期。
當省略 expires 屬性時,其有效期僅限于維持瀏覽器會話(Session)時間段內(nèi)。這通常限于瀏覽器應(yīng)用程序被關(guān)閉之前。
另外,一旦 Cookie 從服務(wù)器端發(fā)送至客戶端,服務(wù)器端就不存在可以顯式刪除 Cookie 的方法。但可通過覆蓋已過期的 Cookie,實現(xiàn)對客戶端 Cookie 的實質(zhì)性刪除操作。
8.1.2 path 屬性
Cookie 的 path 屬性可用于限制指定 Cookie 的發(fā)送范圍的文件目錄。
8.1.3 domain 屬性
通過 Cookie 的 domain 屬性指定的域名可做到與結(jié)尾匹配一致。比如,當指定 example.com 后,除example.com 以外,www.example.com 或 www2.example.com 等都可以發(fā)送 Cookie。
因此,除了針對具體指定的多個域名發(fā)送 Cookie 之 外,不指定 domain 屬性顯得更安全。
8.1.4 secure 屬性
Cookie 的 secure 屬性用于限制 Web 頁面僅在 HTTPS 安全連接時,才可以發(fā)送 Cookie。
8.1.5 HttpOnly 屬性
Cookie 的 HttpOnly 屬性是 Cookie 的擴展功能,它使 JavaScript 腳本無法獲得 Cookie。其主要目的為防止跨站腳本攻擊(Cross-site scripting,XSS)對 Cookie 的信息竊取。
通過上述設(shè)置,通常從 Web 頁面內(nèi)還可以對 Cookie 進行讀取操作。但使用 JavaScript 的 document.cookie 就無法讀取附加 HttpOnly 屬性后的 Cookie 的內(nèi)容了。因此,也就無法在 XSS 中利用 JavaScript 劫持 Cookie 了。
8.2 Cookie
Cookie: status=enable
首部字段 Cookie 會告知服務(wù)器,當客戶端想獲得 HTTP 狀態(tài)管理支持時,就會在請求中包含從服務(wù)器接收到的 Cookie。接收到多個 Cookie 時,同樣可以以多個 Cookie 形式發(fā)送。
9. 其他首部字段
HTTP 首部字段是可以自行擴展的。所以在 Web 服務(wù)器和瀏覽器的應(yīng)用上,會出現(xiàn)各種非標準的首部字段。
以下是最為常用的首部字段。
9.1 X-Frame-Options
X-Frame-Options: DENY
首部字段 X-Frame-Options 屬于 HTTP 響應(yīng)首部,用于控制網(wǎng)站內(nèi)容在其他 Web 網(wǎng)站的 Frame 標簽內(nèi)的顯示問題。其主要目的是為了防止點擊劫持(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 響應(yīng)首部,它是針對跨站腳本攻擊(XSS)的一種對策,用于控制瀏覽器 XSS 防護機制的開關(guān)。首部字段 X-XSS-Protection 可指定的字段值如下:
0 :將 XSS 過濾設(shè)置成無效狀態(tài)
1 :將 XSS 過濾設(shè)置成有效狀態(tài)
9.3 DNT
DNT: 1
首部字段 DNT 屬于 HTTP 請求首部,其中 DNT 是 Do Not Track 的簡稱,意為拒絕個人信息被收集,是表示拒絕被精準廣告追蹤的一種方法。首部字段 DNT 可指定的字段值如下:
0 :同意被追蹤
1 :拒絕被追蹤
由于首部字段 DNT 的功能具備有效性,所以 Web 服務(wù)器需要對 DNT做對應(yīng)的支持。
9.4 P3P
P3P: CP="CAO DSP LAW CURa ADMa DEVa TAIa PSAa PSDa IVAa IVDa OUR BUS IND
首部字段 P3P 屬于 HTTP 響應(yīng)首部,通過利用 P3P(The Platform for Privacy Preferences,在線隱私偏好平臺)技術(shù),可以讓 Web 網(wǎng)站上的個人隱私變成一種僅供程序可理解的形式,以達到保護用戶隱私的目的。
要進行 P3P 的設(shè)定,需按以下操作步驟進行:
步驟 1:創(chuàng)建 P3P 隱私
步驟 2:創(chuàng)建 P3P 隱私對照文件后,保存命名在 /w3c/p3p.xml
步驟 3:從 P3P 隱私中新建 Compact policies 后,輸出到 HTTP 響應(yīng)中
七、HTTP 響應(yīng)狀態(tài)碼(重點分析)
1. 狀態(tài)碼概述
HTTP 狀態(tài)碼負責表示客戶端 HTTP 請求的返回結(jié)果、標記服務(wù)器端的處理是否正常、通知出現(xiàn)的錯誤等工作。
HTTP 狀態(tài)碼如
200 OK,以 3 位數(shù)字和原因短語組成。數(shù)字中的第一位指定了響應(yīng)類別,后兩位無分類。不少返回的響應(yīng)狀態(tài)碼都是錯誤的,但是用戶可能察覺不到這點。比如 Web 應(yīng)用程序內(nèi)部發(fā)生錯誤,狀態(tài)碼依然返回
200 OK。
2. 狀態(tài)碼類別
| 類別 | 原因短語 | |
|---|---|---|
| 1xx | Informational(信息性狀態(tài)碼) | 接收的請求正在處理 |
| 2xx | Success(成功狀態(tài)碼) | 請求正常處理完畢 |
| 3xx | Redirection(重定向狀態(tài)碼) | 需要進行附加操作以完成請求 |
| 4xx | Client Error(客戶端錯誤狀態(tài)碼) | 服務(wù)器無法處理請求 |
| 5xx | Server Error(服務(wù)器錯誤狀態(tài)碼) | 服務(wù)器處理請求出錯 |
我們可以自行改變 RFC2616 中定義的狀態(tài)碼或者服務(wù)器端自行創(chuàng)建狀態(tài)碼,只要遵守狀態(tài)碼的類別定義就可以了。
3. 常用狀態(tài)碼解析
HTTP 狀態(tài)碼種類繁多,數(shù)量達幾十種。其中最常用的有以下 14 種,一起來看看。
3.1 200 OK
表示從客戶端發(fā)來的請求在服務(wù)器端被正常處理了。
3.2 204 No Content
代表服務(wù)器接收的請求已成功處理,但在返回的響應(yīng)報文中不含實體的主體部分。另外,也不允許返回任何實體的主體。
一般在只需要從客戶端向服務(wù)器端發(fā)送消息,而服務(wù)器端不需要向客戶端發(fā)送新消息內(nèi)容的情況下使用。
3.3 206 Partial Content
表示客戶端進行了范圍請求,而服務(wù)器成功執(zhí)行了這部分的 GET 請求。響應(yīng)報文中包含由 Content-Range 首部字段指定范圍的實體內(nèi)容。
3.4 301 Moved Permanently
永久性重定向。表示請求的資源已被分配了新的 URI。以后應(yīng)使用資源現(xiàn)在所指的 URI。也就是說,如果已經(jīng)把資源對應(yīng)的 URI 保存為書簽了,這時應(yīng)該按 Location 首部字段提示的 URI 重新保存。
3.5 302 Found
臨時性重定向。表示請求的資源已被分配了新的 URI,希望用戶(本次)能使用新的 URI 訪問。
和
301 Moved Permanently狀態(tài)碼相似,但302 Found狀態(tài)碼代表資源不是被永久移動,只是臨時性質(zhì)的。換句話說,已移動的資源對應(yīng)的 URI 將來還有可能發(fā)生改變。
3.6 303 See Other
表示由于請求的資源存在著另一個 URI,應(yīng)使用 GET 方法定向獲取請求的資源。
303 See Other 和302 Found狀態(tài)碼有著相同的功能,但303 See Other狀態(tài)碼明確表示客戶端應(yīng)采用 GET 方法獲取資源,這點與302 Found狀態(tài)碼有區(qū)別。
3.7 304 Not Modified
表示客戶端發(fā)送附帶條件的請求時,服務(wù)器端允許請求訪問的資源,但未滿足條件的情況。
304 Not Modified狀態(tài)碼返回時,不包含任何響應(yīng)的主體部分。304 Not Modified雖然被劃分到 3xx 類別中,但和重定向沒有關(guān)系。
3.8 307 Temporary Redirect
臨時重定向。該狀態(tài)碼與 302 Found 有著相同的含義。
3.9 400 Bad Request
表示請求報文中存在語法錯誤。當錯誤發(fā)生時,需修改請求的內(nèi)容后再次發(fā)送請求。
另外,瀏覽器會像
200 OK一樣對待該狀態(tài)碼。
3.10 401 Unauthorized
表示發(fā)送的請求需要有通過 HTTP 認證(BASIC 認證、DIGEST 認證)的認證信息。
另外,若之前已進行過 1 次請求,則表示用戶認證失敗。
返回含有
401 Unauthorized的響應(yīng)必須包含一個適用于被請求資源的 WWW-Authenticate 首部用以質(zhì)詢(challenge)用戶信息。
3.11 403 Forbidden
表明對請求資源的訪問被服務(wù)器拒絕了。服務(wù)器端沒有必要給出詳細的拒絕理由,當然也可以在響應(yīng)報文的實體主體部分對原因進行描述。
3.12 404 Not Found
表明服務(wù)器上無法找到請求的資源。除此之外,也可以在服務(wù)器端拒絕請求且不想說明理由的時候使用。
3.13 500 Internal Server Error
表明服務(wù)器端在執(zhí)行請求時發(fā)生了錯誤。也可能是 Web 應(yīng)用存在的 bug 或某些臨時的故障。
3.14 503 Service Unavailable
表明服務(wù)器暫時處于超負載或正在進行停機維護,現(xiàn)在無法處理請求。如果事先得知解除以上狀況需要的時間,最好寫入 Retry-After 首部字段再返回給客戶端。
八、HTTP 報文實體
1. HTTP 報文實體概述

HTTP 報文結(jié)構(gòu)
大家請仔細看看上面示例中,各個組成部分對應(yīng)的內(nèi)容。
接著,我們來看看報文和實體的概念。如果把 HTTP 報文想象成因特網(wǎng)貨運系統(tǒng)中的箱子,那么 HTTP 實體就是報文中實際的貨物。
報文:是網(wǎng)絡(luò)中交換和傳輸?shù)臄?shù)據(jù)單元,即站點一次性要發(fā)送的數(shù)據(jù)塊。報文包含了將要發(fā)送的完整的數(shù)據(jù)信息,其長短很不一致,長度不限且可變。
實體:作為請求或響應(yīng)的有效載荷數(shù)據(jù)(補充項)被傳輸,其內(nèi)容由實體首部和實體主體組成。(實體首部相關(guān)內(nèi)容在上面第六點中已有闡述。)
我們可以看到,上面示例右圖中深紅色框的內(nèi)容就是報文的實體部分,而藍色框的兩部分內(nèi)容分別就是實體首部和實體主體。而左圖中粉紅框內(nèi)容就是報文主體。
通常,報文主體等于實體主體。只有當傳輸中進行編碼操作時,實體主體的內(nèi)容發(fā)生變化,才導致它和報文主體產(chǎn)生差異。
2. 內(nèi)容編碼
HTTP 應(yīng)用程序有時在發(fā)送之前需要對內(nèi)容進行編碼。例如,在把很大的 HTML 文檔發(fā)送給通過慢速連接上來的客戶端之前,服務(wù)器可能會對其進行壓縮,這樣有助于減少傳輸實體的時間。服務(wù)器還可以把內(nèi)容攪亂或加密,以此來防止未授權(quán)的第三方看到文檔的內(nèi)容。
這種類型的編碼是在發(fā)送方應(yīng)用到內(nèi)容之上的。當內(nèi)容經(jīng)過內(nèi)容編碼后,編好碼的數(shù)據(jù)就放在實體主體中,像往常一樣發(fā)送給接收方。
內(nèi)容編碼類型:
| 編碼方式 | 描述 |
|---|---|
| gzip | 表明實體采用 GNU zip 編碼 |
| compress | 表明實體采用 Unix 的文件壓縮程序 |
| deflate | 表明實體采用 zlib 的格式壓縮的 |
| identity | 表明沒有對實體進行編碼,當沒有 Content-Encoding 首部字段時,默認采用此編碼方式 |
3. 傳輸編碼
內(nèi)容編碼是對報文的主體進行的可逆變換,是和內(nèi)容的具體格式細節(jié)緊密相關(guān)的。
傳輸編碼也是作用在實體主體上的可逆變換,但使用它們是由于架構(gòu)方面的原因,同內(nèi)容的格式無關(guān)。使用傳輸編碼是為了改變報文中的數(shù)據(jù)在網(wǎng)絡(luò)上傳輸?shù)姆绞健?/span>

內(nèi)容編碼和傳輸編碼的對比
4. 分塊編碼
分塊編碼把報文分割成若干已知大小的塊。塊之間是緊挨著發(fā)送的,這樣就不需要在發(fā)送之前知道整個報文的大小了。分塊編碼是一種傳輸編碼,是報文的屬性。
分塊編碼與持久連接
若客戶端與服務(wù)器端之間不是持久連接,客戶端就不需要知道它在讀取的主體的長度,而只需要讀取到服務(wù)器關(guān)閉主體連接為止。
當使用持久連接時,在服務(wù)器寫主體之前,必須知道它的大小并在 Content-Length 首部中發(fā)送。如果服務(wù)器動態(tài)創(chuàng)建內(nèi)容,就可能在發(fā)送之前無法知道主體的長度。
分塊編碼為這種困難提供了解決方案,只要允許服務(wù)器把主體分塊發(fā)送,說明每塊的大小就可以了。因為主體是動態(tài)創(chuàng)建的,服務(wù)器可以緩沖它的一部分,發(fā)送其大小和相應(yīng)的塊,然后在主體發(fā)送完之前重復這個過程。服務(wù)器可以用大小為 0 的塊作為主體結(jié)束的信號,這樣就可以繼續(xù)保持連接,為下一個響應(yīng)做準備。
來看看一個分塊編碼的報文示例:

分塊編碼的報文
5.多部分媒體類型
MIME 中的 multipart(多部分)電子郵件報文中包含多個報文,它們合在一起作為單一的復雜報文發(fā)送。每一部分都是獨立的,有各自的描述其內(nèi)容的集,不同部分之間用分界字符串連接在一起。
相應(yīng)得,HTTP 協(xié)議中也采納了多部分對象集合,發(fā)送的一份報文主體內(nèi)可包含多種類型實體。
多部分對象集合包含的對象如下:
multipart/form-data:在 Web 表單文件上傳時使用。
multipart/byteranges:狀態(tài)碼
206 Partial Content響應(yīng)報文包含了多個范圍的內(nèi)容時使用。
6. 范圍請求
假設(shè)你正在下載一個很大的文件,已經(jīng)下了四分之三,忽然網(wǎng)絡(luò)中斷了,那下載就必須重頭再來一遍。為了解決這個問題,需要一種可恢復的機制,即能從之前下載中斷處恢復下載。要實現(xiàn)該功能,這就要用到范圍請求。
有了范圍請求, HTTP 客戶端可以通過請求曾獲取失敗的實體的一個范圍(或者說一部分),來恢復下載該實體。當然這有一個前提,那就是從客戶端上一次請求該實體到這一次發(fā)出范圍請求的時間段內(nèi),該對象沒有改變過。例如:
GET /bigfile.html HTTP/1.1
Host: www.sample.com
Range: bytes=20224-
···

上面示例中,客戶端請求的是文檔開頭20224字節(jié)之后的部分。
九、與 HTTP 協(xié)作的 Web 服務(wù)器
HTTP 通信時,除客戶端和服務(wù)器外,還有一些用于協(xié)助通信的應(yīng)用程序。如下列出比較重要的幾個:代理、緩存、網(wǎng)關(guān)、隧道、Agent 代理。
1.代理

HTTP 代理服務(wù)器是 Web 安全、應(yīng)用集成以及性能優(yōu)化的重要組成模塊。代理位于客戶端和服務(wù)器端之間,接收客戶端所有的 HTTP 請求,并將這些請求轉(zhuǎn)發(fā)給服務(wù)器(可能會對請求進行修改之后再進行轉(zhuǎn)發(fā))。對用戶來說,這些應(yīng)用程序就是一個代理,代表用戶訪問服務(wù)器。
出于安全考慮,通常會將代理作為轉(zhuǎn)發(fā)所有 Web 流量的可信任中間節(jié)點使用。代理還可以對請求和響應(yīng)進行過濾,安全上網(wǎng)或綠色上網(wǎng)。
2. 緩存
瀏覽器第一次請求:

瀏覽器第一次請求
瀏覽器再次請求:

瀏覽器再次請求
Web 緩存或代理緩存是一種特殊的 HTTP 代理服務(wù)器,可以將經(jīng)過代理傳輸?shù)某S梦臋n復制保存起來。下一個請求同一文檔的客戶端就可以享受緩存的私有副本所提供的服務(wù)了??蛻舳藦母浇木彺嫦螺d文檔會比從遠程 Web 服務(wù)器下載快得多。
3. 網(wǎng)關(guān)

HTTP / FTP 網(wǎng)關(guān)
網(wǎng)關(guān)是一種特殊的服務(wù)器,作為其他服務(wù)器的中間實體使用。通常用于將 HTTP 流量轉(zhuǎn)換成其他的協(xié)議。網(wǎng)關(guān)接收請求時就好像自己是資源的源服務(wù)器一樣??蛻舳丝赡懿⒉恢雷约赫诟粋€網(wǎng)關(guān)進行通信。
4. 隧道

HTTP/SSL 隧道
隧道是會在建立起來之后,就會在兩條連接之間對原始數(shù)據(jù)進行盲轉(zhuǎn)發(fā)的 HTTP 應(yīng)用程序。HTTP 隧道通常用來在一條或多條 HTTP 連接上轉(zhuǎn)發(fā)非 HTTP 數(shù)據(jù),轉(zhuǎn)發(fā)時不會窺探數(shù)據(jù)。
HTTP 隧道的一種常見用途就是通過 HTTP 連接承載加密的安全套接字層(SSL)流量,這樣 SSL 流量就可以穿過只允許 Web 流量通過的防火墻了。
5. Agent 代理

Agent 代理是代表用戶發(fā)起 HTTP 請求的客戶端應(yīng)用程序。所有發(fā)布 Web 請求的應(yīng)用程序都是 HTTP Agent 代理。

