1. 程式人生 > >第6章 HTTP首部(上)

第6章 HTTP首部(上)

6.1 HTTP 報文首部
HTTP 請求報文
HTTP 響應報文
6.2 HTTP 首部欄位
6.2.1 HTTP 首部欄位傳遞重要資訊
6.2.2 HTTP 首部欄位結構
6.2.3 4 種 HTTP 首部欄位型別
6.2.4 HTTP/1.1 首部欄位一覽
6.2.5 非 HTTP/1.1 首部欄位
6.2.6 End-to-end 首部和 Hop-by-hop 首部
6.3 HTTP/1.1通用首部欄位
6.3.1 Cache-Control
6.3.2 Connection
6.3.3 Date
6.3.4 Pragma
6.3.5 Trailer
6.3.6 Transfer-Encoding
6.3.7 Upgrade
6.3.8 Via
6.3.9 Warning

HTTP 協議的請求和響應報文中必定包含 HTTP 首部,只是我們平 時在使用 Web 的過程中感受不到它。本章我們一起來學習 HTTP 首部的結構,以及首部中各欄位的用法

6.1 HTTP報文首部

在這裡插入圖片描述
HTTP 協議的請求和響應報文中必定包含 HTTP 首部。首部內容為客戶端和伺服器分別處理請求和響應提供所需要的資訊。對於客戶端使用者來說,這些資訊中的大部分內容都無須親自檢視。

報文首部由幾個欄位構成。

HTTP 請求報文

在請求中,HTTP 報文由方法、URI、HTTP 版本、HTTP 首部欄位等部分構成。
下面的示例是訪問 http://hackr.jp

時,請求報文的首部資訊。

GET / HTTP/1.1
Host: hackr.jp
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:13.0) Gecko/20100101 Firefox/13.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*; q=0.8
Accept-Language: ja,en-us;q=0.7,en;q=0.3
Accept-Encoding: gzip, deflate
DNT: 1
Connection: keep-alive
If-Modified-Since: Fri, 31 Aug 2007 02:02:20 GMT
If-None-Match: "45bae1-16a-46d776ac"
Cache-Control: max-age=0

HTTP 響應報文

在響應中,HTTP 報文由 HTTP 版本、狀態碼(數字和原因短語)、HTTP 首部欄位 3 部分構成。
在這裡插入圖片描述
以下示例是之前請求訪問 http://hackr.jp/ 時,返回的響應報文的首部資訊

HTTP/1.1 304 Not Modified
Date: Thu, 07 Jun 2012 07:21:36 GMT
Server: Apache
Connection: close
Etag: "45bae1-16a-46d776ac"

在報文眾多的欄位當中,HTTP 首部欄位包含的資訊最為豐富。首部欄位同時存在於請求和響應報文內,並涵蓋 HTTP 報文相關的內容資訊。

因 HTTP 版本或擴充套件規範的變化,首部欄位可支援的欄位內容略有不同。本書主要涉及 HTTP/1.1 及常用的首部欄位。

6.2 HTTP 首部欄位

6.2.1 HTTP 首部欄位傳遞重要資訊

HTTP 首部欄位是構成 HTTP 報文的要素之一。在客戶端與伺服器之間以 HTTP 協議進行通訊的過程中,無論是請求還是響應都會使用首部欄位,它能起到傳遞額外重要資訊的作用。

使用首部欄位是為了給瀏覽器和伺服器提供報文主體大小、所使用的語言、認證資訊等內容。
在這裡插入圖片描述

6.2.2 HTTP 首部欄位結構

HTTP 首部欄位是由首部欄位名和欄位值構成的,中間用冒號“:” 分隔。

首部欄位名: 欄位值

例如,在 HTTP 首部中以 Content-Type 這個欄位來表示報文主體的 物件型別。

Content-Type: text/html

就以上述示例來看,首部欄位名為 Content-Type,字串 text/html 是欄位值。

另外,欄位值對應單個 HTTP 首部欄位可以有多個值,如下所示。

Keep-Alive: timeout=15, max=100

當 HTTP 報文首部中出現了兩個或兩個以上具有相同首部欄位名時會怎麼樣?這種情況在規範內尚未明確,根據瀏覽器內部處理邏輯的不同,結果可能並不一致。有些瀏覽器會優先處理第一次出現的首部欄位,而有些則會優先處理最後出現的首部欄位。

6.2.3 4 種 HTTP 首部欄位型別

HTTP 首部欄位根據實際用途被分為以下 4 種類型。

通用首部欄位(General Header Fields)
請求報文和響應報文兩方都會使用的首部。

請求首部欄位(Request Header Fields)
從客戶端向伺服器端傳送請求報文時使用的首部。補充了請求的附加內容、客戶端資訊、響應內容相關優先順序等資訊。

響應首部欄位(Response Header Fields)

從伺服器端向客戶端返回響應報文時使用的首部。補充了響應的附加內容,也會要求客戶端附加額外的內容資訊。

實體首部欄位(Entity Header Fields)
針對請求報文和響應報文的實體部分使用的首部。補充了資源內容更新時間等與實體有關的資訊。

6.2.4 HTTP/1.1 首部欄位一覽

HTTP/1.1 規範定義瞭如下 47 種首部欄位。
在這裡插入圖片描述

在這裡插入圖片描述
在這裡插入圖片描述
在這裡插入圖片描述

在這裡插入圖片描述

6.2.5 非 HTTP/1.1 首部欄位

在 HTTP 協議通訊互動中使用到的首部欄位,不限於 RFC2616 中定義的 47 種首部欄位。還有 Cookie、Set-Cookie 和 Content-Disposition 等在其他 RFC 中定義的首部欄位,它們的使用頻率也很高。

這些非正式的首部欄位統一歸納在 RFC4229 HTTP Header Field Registrations 中。

6.2.6 End-to-end 首部和 Hop-by-hop 首部

HTTP 首部欄位將定義成快取代理和非快取代理的行為,分成 2 種類型。

端到端首部(End-to-end Header)

分在此類別中的首部會轉發給請求 / 響應對應的最終接收目標,且必須儲存在由快取生成的響應中,另外規定它必須被轉發。

逐跳首部(Hop-by-hop Header)

分在此類別中的首部只對單次轉發有效,會因通過快取或代理而不再轉發。HTTP/1.1 和之後版本中,如果要使用 hop-by-hop 首部,需提供 Connection 首部欄位。

下面列舉了 HTTP/1.1 中的逐跳首部欄位。除這 8 個首部欄位之外,其他所有欄位都屬於端到端首部。

Connection

Keep-Alive

Proxy-Authenticate

Proxy-Authorization

Trailer

TE

Transfer-Encoding

Upgrade

6.3 HTTP/1.1通用首部欄位

通用首部欄位是指,請求報文和響應報文雙方都會使用的首部。

6.3.1 Cache-Control

通過指定首部欄位 Cache-Control 的指令,就能操作快取的工作機制。
在這裡插入圖片描述
圖:首部欄位 Cache-Control 能夠控制快取的行為

指令的引數是可選的,多個指令之間通過“,”分隔。首部欄位 Cache-Control 的指令可用於請求及響應時。

Cache-Control: private, max-age=0, no-cache

Cache-Control 指令一覽
可用的指令按請求和響應分類如下所示。
在這裡插入圖片描述
在這裡插入圖片描述

表示是否能快取的指令

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-cache 代表不快取過期的資源,快取會向源伺服器進行有效期確認後處理資源,也許稱為 do-not-serve-from-cache-without-revalidation 更合適。no-store 才是真正地不進行快取,請讀者注意區別理解。

因此,該指令規定快取不能在本地儲存請求或響應的任一部分。

指定快取期限和認證的指令
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 版本的快取伺服器的情況卻相反,max-age 指令會被忽略掉。

min-fresh 指令
在這裡插入圖片描述

Cache-Control: min-fresh=60(單位:秒)

min-fresh 指令要求快取伺服器返回至少還未過指定時間的快取資源。

比如,當指定 min-fresh 為 60 秒後,在這 60 秒以內如果有超過有效期限的資源都無法作為響應返回了。

max-stale 指令

Cache-Control: max-stale=3600(單位:秒)

使用 max-stale 可指示快取資源,即使過期也照常接收。

如果指令未指定引數值,那麼無論經過多久,客戶端都會接收響應;如果指令中指定了具體數值,那麼即使過期,只要仍處於 max-stale 指定的時間內,仍舊會被客戶端接收。

only-if-cached 指令

Cache-Control: only-if-cached

使用 only-if-cached 指令表示客戶端僅在快取伺服器本地快取目標資源的情況下才會要求其返回。換言之,該指令要求快取伺服器不重新載入響應,也不會再次確認資源有效性。若發生請求快取伺服器的本地快取無響應,則返回狀態碼 504 Gateway Timeout。

must-revalidate 指令

Cache-Control: must-revalidate

使用 must-revalidate 指令,代理會向源伺服器再次驗證即將返回的響應快取目前是否仍然有效。

若代理無法連通源伺服器再次獲取有效資源的話,快取必須給客戶端一條 504(Gateway Timeout)狀態碼。

另外,使用 must-revalidate 指令會忽略請求的 max-stale 指令(即使已經在首部使用了 max-stale,也不會再有效果)。

proxy-revalidate 指令

Cache-Control: proxy-revalidate

proxy-revalidate 指令要求所有的快取伺服器在接收到客戶端帶有該指令的請求返回響應之前,必須再次驗證快取的有效性。

no-transform 指令

Cache-Control: no-transform

使用 no-transform 指令規定無論是在請求還是響應中,快取都不能改變實體主體的媒體型別。

這樣做可防止快取或代理壓縮圖片等類似操作。

Cache-Control 擴充套件
cache-extension token

Cache-Control: private, community="UCI"

通過 cache-extension 標記(token),可以擴充套件 Cache-Control 首部欄位內的指令。

如上例,Cache-Control 首部欄位本身沒有 community 這個指令。藉助 extension tokens 實現了該指令的新增。如果快取伺服器不能理解 community 這個新指令,就會直接忽略。因此,extension tokens 僅對能理解它的快取伺服器來說是有意義的。

6.3.2 Connection

Connection 首部欄位具備如下兩個作用:
(1)控制代理不再轉發的首部欄位
(2)管理持久連線

控制代理不再轉發的首部欄位
在這裡插入圖片描述

Connection: 不再轉發的首部欄位名

在客戶端傳送請求和伺服器返回響應內,使用 Connection 首部欄位,可控制代理不再轉發的首部欄位(即 Hop-by-hop 首部)。

管理持久連線
在這裡插入圖片描述

Connection: close

HTTP/1.1 版本的預設連線都是持久連線。為此,客戶端會在持久連線上連續傳送請求。當伺服器端想明確斷開連線時,則指定 Connection 首部欄位的值為 Close。
在這裡插入圖片描述

Connection: Keep-Alive

HTTP/1.1 之前的 HTTP 版本的預設連線都是非持久連線。為此,如果想在舊版本的 HTTP 協議上維持持續連線,則需要指定 Connection 首部欄位的值為 Keep-Alive。

如上圖①所示,客戶端傳送請求給伺服器時,伺服器端會像上圖②那樣加上首部欄位 Keep-Alive 及首部欄位 Connection 後返回響應。

6.3.3 Date

首部欄位 Date 表明建立 HTTP 報文的日期和時間。
在這裡插入圖片描述
HTTP/1.1 協議使用在 RFC1123 中規定的日期時間的格式,如下 示例。

Date: Tue, 03 Jul 2012 04:40:59 GMT

之前的 HTTP 協議版本中使用在 RFC850 中定義的格式,如下所示。

Date: Tue, 03-Jul-12 04:40:59 GMT

除此之外,還有一種格式。它與 C 標準庫內的 asctime() 函式的輸出格式一致。

Date: Tue Jul 03 04:40:59 2012

6.3.4 Pragma

6.3.5 Trailer

6.3.6 Transfer-Encoding

6.3.7 Upgrade

6.3.8 Via

6.3.9 Warning