轉載請註明出處:
文章目錄
1.與HTTP協議相關的Web伺服器
2.HTTP首部
與HTTP協議相關的Web伺服器
在說明HTTP首部相關知識之前,有必要先了解一下與HTTP協作的Web伺服器。
用一臺主機實現多個域名
HTTP/1.1規範明確提出,允許一臺Web伺服器實現多個域名。即使物理層面上只有一臺伺服器,但只要使用虛擬主機(又稱虛擬伺服器)的功能,就可以假想已經具有多臺伺服器。
虛擬主機,又可以叫做虛擬伺服器,是一種在單一主機獲主機群上,實現多網域服務的方法,可以執行多個網站或服務的技術。具體內容可參考wiki。傳送門:wiki: 虛擬主機
但是在同一臺伺服器上部署多個網站域名會有一個問題,因為只有一臺物理伺服器,意味著只有一個IP地址,在DNS服務將域名解析成IP地址之後,在收到請求之後就需要弄清楚究竟要訪問哪個域名。
這個問題其實有兩種方法可以解決。一是在傳送請求時必須請求頭部欄位中增加Host欄位,表明請求的主機名。二是在一臺伺服器上使用不同的IP地址來管理多個服務。
通訊資料轉發程式:代理
代理伺服器位於伺服器和客戶端之間,接收由客戶端傳送的請求並轉發給伺服器,同時也接收伺服器返回的響應並轉發給客戶端。前端工程師常用的抓包軟體Fiddler、Charles就是通過代理來實現抓包的。
代理伺服器的基本行為就是接收客戶端傳送的請求後轉發給伺服器,代理不改變請求URI,會直接傳送給前方具有資源的目標伺服器。持有資源實體的伺服器稱為源伺服器,從源伺服器返回的響應經過代理伺服器後再傳給客戶端。每經過一次代理伺服器,都會追加Via首部欄位資訊,表明經過的代理伺服器資訊。要不然都不知道誰跟誰了...
總的來說呢,使用代理伺服器有以下好處
1.利用快取技術減少伺服器網路頻寬流量的消耗
2.針對特定網站的訪問控制(控制哪些站點可以訪問伺服器,哪些不能訪問,實現訪問過濾功能)
代理有多種使用方法,按照兩種基準分類,一種是是否快取(快取代理),另一種是是否會修改報文(透明代理)。詳細資料可參見wiki。傳送門:wiki: 代理伺服器
儲存資源的快取
上面所說的快取技術是指代理伺服器或客戶端本地磁碟內儲存的資源副本。利用快取可以減少對源伺服器的訪問(從代理伺服器或瀏覽器讀取未過期的快取資源),因此也就節省了通訊流量和通訊時間了。
快取(代理)伺服器的優勢在於利用快取可避免多次從源伺服器請求資源。因此客戶端可就近從瀏覽器或代理伺服器上獲取資源,而源伺服器也不必多次處理相同的請求了。
但是不管是瀏覽器或者是代理伺服器上快取的資源,都存在快取過期的情況。如果快取未過期,那麼就可以直接讀取快取資源;如果快取過期了,代理伺服器將會再次從源伺服器上獲取更新之後的資源。而瀏覽器並不會馬上發起一個請求給伺服器,而是會發起一個條件GET請求(If-Modified-Since和Last-Modified欄位)。
稍微總結一下。
1.一臺Web伺服器可以配置多個域名,在請求時需要新增Host欄位表示請求的主機名或者是多個IP管理不同的服務。
2.代理伺服器的基本行為是將客戶端傳送的請求轉發給伺服器,然後直接將請求資源直接轉發給源伺服器。可以利用代理伺服器或者瀏覽器對響應進行快取,減少同一請求對源伺服器的訪問所產生的頻寬資源的浪費。
HTTP首部
請求頭和響應頭共有的首部欄位包括:通用首部欄位、實體首部欄位、其他首部欄位。而請求頭特有的首部欄位是請求首部欄位,響應頭特有的首部欄位是響應首部欄位。以下是HTTP/1.1定義了47種首部欄位。
以下就簡單的說明一下每一個欄位。
HTTP/1.1通用首部欄位
通用首部欄位是指,請求報文和響應報文雙方都會使用的首部。
Cache-Control指令:
能夠控制快取的工作行為。指令的引數是可選的,多個指令之間通過','分隔。Cache-Control指令可用於請求和響應時。
public: 快取響應指令。明確表明其他使用者也可以利用快取。
private: 快取響應指令。表示響應只以特定的使用者作為物件,代理伺服器只會對特定使用者提供快取資源,對於其他使用者傳送過去來的請求,代理伺服器則不會返回快取。
no-cache: 目的是為了防止從快取中返回過期的資源。客戶端傳送的請求如果包含no-cache指令,表示客戶端將不會接收快取過的響應。於是,代理伺服器必須把客戶端請求轉發給源伺服器。如果伺服器返回的響應中包含no-cache指令,那麼代理伺服器不能對資源進行快取。源伺服器以後也將不再對代理伺服器請求中提出的資源有效性進行確認,且禁止其對響應資源進行快取操作。
no-store: 禁止代理伺服器快取響應資源。
s-maxage: 表示處於公共代理伺服器情況下快取過期沒有超過指定時間時,就會返回快取。對於向同一個使用者重複返回響應的伺服器來說,這個指令沒有任何作用。另外呢,當使用s-maxage指令後,則直接忽略對Expires首部欄位及max-age指令的處理。例如Cache-Control: s-maxage=600(秒)
表示公共代理伺服器中快取過期沒超過10分鐘則可以返回快取資源。
max-age: 形式為Cache-Control: max-age=600(秒)
。如果客戶端傳送的請求中包含max-age指令時,表示快取過期沒超過指定的時間,那麼客戶端就接收快取的資源。如果max-age值為0,表示代理伺服器需要將請求轉發給源伺服器。
當源伺服器返回的響應中包含max-age指令時,代理伺服器將不對資源的有效性進行確認,而max-age數值代表資源儲存為快取的最長時間。
在HTTP/1.1版本的代理伺服器遇到同時存在Expires欄位的情況下,會優先處理max-age指令而忽略掉Expires欄位。
min-fresh: 要求代理伺服器返回至少還沒有超過指定時間的快取資源。如Cache-Control: min-fresh=60(秒)
當指定min-fresh為60秒後,60秒內的響應可以返回,而超過60秒的響應就無法返回了。
max-stale: 表示快取過期在指定時間內,客戶仍然會接收。如果未指定任何引數值,那麼無論經過多久,客戶端都會接受響應。
only-if-cached: 表示客戶端僅在代理伺服器本地快取目標資源的情況下才會要求其返回。也就是說,該指令會要求代理伺服器不重新載入響應,也不會再次確認資源的有效性。若發生請求代理伺服器的本地快取無響應,則返回狀態碼504 Gateway Timeout
must-revalidate: 表示代理伺服器會向源伺服器再次驗證即將返回的響應快取是否仍然有效。如果代理無法連通源伺服器再次獲取有效資源的話,代理伺服器會給客戶端返回504(Gateway Timeout)狀態碼。另外會忽略請求的max-stale指令。
proxy-revalidate: 要求代理伺服器對快取的響應有效性再進行驗證。
no-transform: 無論是在請求中還是在響應頭中,快取都不能改變實體主體的媒體型別。
Connection
Connection欄位具有以下兩個作用
控制不再轉發給代理伺服器的首部欄位: 格式如下Connection: 不再轉發的首部欄位名
。在客戶端傳送請求和伺服器返回響應內,使用Connection欄位可以控制不在轉發給代理伺服器
持久連線: 即Connection: keep-alive
。HTTP/1.1版本預設連線是持久連線。客戶端和伺服器只需建立一次TCP連線,就可以相互進行多次HTTP通訊了。直到有一方明確表示需要斷開TCP連線,持久連線才會結束。
Pragma
該首部欄位僅作為與HTTP/1.0的向後相容而定義。形式如下Pragma: no-cache
。只用在響應頭中,表示代理伺服器不能對響應進行快取。
pargma首部欄位與no-cache指令作用相同,但是為了相容HTTP協議版本的問題,HTTP響應頭中會同時含有下面兩個欄位。
Trailer
Trailer欄位會事先說明在報文主體後記錄了哪些首部欄位。主要用於HTTP/1.1版本的分塊傳輸編碼時。
Transfer-Encoding
Transfer-Encoding欄位規定了傳輸報文主體時採用的編碼方式,僅對分塊傳輸編碼有效。
HTTP/1.1 200 OK
Transfer-Encoding: chunked
Connection: keep-alive
cfo <--16進位制(10進製為3312)
·····3312位元組分塊資料·····
392 <--16進位制(10進製為914)
·····914位元組分塊資料······
複製程式碼
以上例子中,Transfer-Encoding欄位值有效使用分塊傳輸編碼,且被分成了3312位元組和914位元組大小的分塊資料。
Upgrade
Upgrade欄位檢測HTTP協議及其他協議是否可以使用更高的版本進行通訊。如在使用WebSocket協議時會使用到此欄位,在HTTP通訊過程中,會使用HTTP升級將HTTP協議升級為WebSocket協議。之後伺服器端返回101 Switching Protocols狀態碼錶示協議轉換成功,此時就可以使用WebSocket協議進行全雙工雙向通訊了。對WebSocket不熟悉的朋友可以參考這篇文章。傳送門:WebSocket協議解析
Via
Via欄位的目的是為了追蹤客戶端與伺服器之間的請求和響應報文的傳輸路徑。報文在經過代理伺服器或閘道器時,會在Via欄位中附加自身伺服器的資訊,然後再進行轉發。通常Via欄位會與Max-Forwards欄位配合使用。對Max-Forwards欄位的解釋請看這篇文章。傳送門: Max-Forwards
請求首部欄位
Accept
Accept欄位可以通知伺服器,使用者代理能夠處理的媒體型別及媒體型別的相對優先順序。可以使用type/subtype這種形式,一次指定多種媒體型別,通過q=來給媒體型別增加優先順序,最大為1.0, 最小為0,預設值為1.0
Accept:q=1.0 application/json; q=0.8 text/plain; q=0.7 */*
複製程式碼
Accept-Charset
Accept-Charset欄位用來通知伺服器使用者代理支援的字符集及字符集的相對優先順序。另外,可一次性指定多種字符集。與Accept欄位相同的是可用權重q值來表示相對優先順序。
Accept-Encoding
Accept-Encoding欄位用來通知伺服器使用者代理支援的內容編碼及內容編碼的相對優先順序。內容編碼包括gzip、compress、deflate、identity(不執行壓縮的預設編碼格式)等。
Accept-Language
Accept-Language用來告知伺服器使用者代理能夠處理的自然語言集(中文或者英文), 以及自然語言集的相對優先順序,可一次性指定多種自然語言集
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8
複製程式碼
Authorization
Authorization欄位用來告知伺服器,使用者代理的認證資訊(證書)。通常想要通過伺服器認證的使用者代理會在接收到返回的401狀態碼響應後,把欄位Authorization加入請求中。
Host
Host欄位會告知伺服器請求的資源所處的網際網路主機名和埠號。請求被髮送到伺服器時,會使用DNS服務將域名解析成IP地址。如果此時相同的IP地址下部署了多個域名(虛擬主機),那麼伺服器就無法理解究竟是哪個域名對應的請求。因此就需要使用Host欄位來明確指出請求的主機名。
If-None-Match If-None-Match欄位與Etag配合使用,當與Etag欄位值不一致時,伺服器會處理請求。如果一致,則伺服器端會返回304 Not Modified。
在典型的用法中,當一個URL被請求,Web伺服器會返回資源和其對應的Etag值,會被放置在HTTP響應頭中。
Etag: "686897696a7c876b7e"
複製程式碼
然後,客戶端可以決定是否快取這個資源和Etag。以後,如果客戶端想再次請求相同的url,將會傳送一個包含已儲存的Etag和If-None-Match欄位的請求。
If-None-Match: "686897696a7c876b7e"
複製程式碼
客戶端請求之後,伺服器可能會比較客戶端的Etag和當前版本資源的ETag。如果ETag值匹配,這就意味著資源沒有改變,伺服器便會傳送回一個極短的響應,包含HTTP “304 Not Modified”的狀態。304狀態告訴客戶端,它的快取版本是最新的,並應該使用它。 然而,如果ETag的值不匹配,這就意味著資源很可能發生了變化,那麼,一個完整的響應(200 OK)就會被返回,包括資源的內容,就好像ETag沒有被使用。這種情況下,客戶端可以用新返回的資源和新的ETag替代先前的快取版本。
If-Modified-Since
If-Modified-Since欄位與響應頭的Last-Modified欄位匹配使用。當Last-Modified欄位值的時間在其之後,表示資源發生了更新,則伺服器會返回200 OK的狀態碼,當Last-Modified欄位值的時間在其之前,表明資源沒有發生更新,則伺服器會返回304 Not Modified狀態碼。當與If-None-Match欄位聯合使用的時候,If-Modified-Since欄位會被忽略,除非伺服器不支援If-None-Match欄位。If-Modified-Since用於確認代理伺服器或客戶端擁有的本地資源的有效性。
If-Range
If-Range欄位會告知伺服器若指定的If-Range欄位值和請求資源的Etag值獲時間相一致,則作為範圍請求處理,返回的響應頭會包含Content-Range欄位,表示返回的範圍位元組數。反之,則返回全體資源。此欄位會與Range欄位配合使用。
Proxy-Authorization
Proxy-Authorization: Basic dFDGADdjgjadfDSFJ5
複製程式碼
接收到代理伺服器傳送過來的認證資訊之後,客戶端會傳送包含該首部欄位的請求,以告知伺服器認證所需要的資訊。
Referer
Referer欄位會告知伺服器請求的原始資源的URI。
響應首部欄位
Accept-Ranges
Accpet-Ranges欄位用來告知客戶端伺服器能否處理範圍請求,以指定獲取伺服器端某個部分的資源。可指定的欄位值有兩種,可處理範圍請求時指定其為bytes,反之指定為none。
ETag
伺服器會為每份資源分配對應的ETag值,當資源更新時,ETag值也需要更新。ETag欄位通常與If-None-Match欄位配合使用。當ETag值與If-None-Match值相互匹配時,表示請求的資源沒有發生變化,則伺服器會返回304 Not Modified狀態碼;如果相互不匹配,則會返回200 OK狀態碼。另外,ETag分為強ETag和弱ETag,它們通過ETag識別符號的開頭是否存在“W/”來區分,如
"123456789" -- 一個強ETag驗證符
W/"123456789" -- 一個弱ETag驗證符
複製程式碼
具體的區別可參考wiki。傳送門: HTTP ETag
Proxy-Authenticate && WWW-Authenticate Proxy-Authenticate欄位會把有代理伺服器所要求的認證資訊傳送給客戶端,通常與Proxy-Authorization欄位配合使用。
WWW-Authenticate欄位用於HTTP訪問認證。通常與Authorization欄位配合使用。
實體首部欄位
實體首部欄位是包含在請求報文和響應報文中的實體部分所使用的首部,用於補充內容的更新時間等與實體相關的資訊。 Allow
形式如Allow: GET, POST
。Allow欄位用於通知客戶端能夠支援的HTTP方法。當伺服器接收到不支援的HTTP方法時,會以狀態碼405 Method Not Allowed作為響應返回。
Content-Encoding
該欄位會告知客戶端伺服器對實體的主體部分選用的內容編碼方式。主要採用4種內容編碼方式:gzip、compress、deflate、identity。
Content-Language && Content-Length
Content-Language告知客戶端實體主體採用的自然語言集。Content-Length告知客戶端實體主體的大小。
Content-Range && Content-Type
Content-Range告知客戶端響應返回的實體的哪個部分符合範圍請求,該欄位針對範圍請求。欄位值以位元組為單位,表示當前傳送部分及整個實體大小。形式如Content-Range: bytes 5001-10000/10000
Content-Type告知客戶端實體主體採用的媒體型別,媒體型別與Accept欄位相同。
Expries
Expries欄位用於告知客戶端資源的過期時間。如果是代理伺服器接收到帶有Expires欄位的響應時,會將資源快取起來。當請求相同資源且未超過指定時間時,會返回快取的資源。當超過指定時間後,代理伺服器會將請求轉發給源伺服器。如果不希望代理伺服器對資源進行快取時,可以將Expires欄位設定成與Date欄位的值相同。在瀏覽器方面,當請求的資源過期時,不會立馬向源伺服器發起請求,而是會先發起條件請求(If-Modified-Since與Last-Modifed欄位)。
當Expires欄位遇上Cache-Control欄位的max-age指令時,會優先處理max-age指令。
為Cookie服務的欄位
由於HTTP是無狀態協議,因此需要Cookie結合HTTP來實現使用者的狀態管理。對於Cookie的說明可以看這篇文章。傳送門:前端儲存方案
參考資料
1.《圖解HTTP》
3.維基百科