成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

漫談:HTTP網(wǎng)絡(luò)協(xié)議中Vary響應(yīng)頭

網(wǎng)絡(luò) 網(wǎng)絡(luò)管理
經(jīng)常抓包看 HTTP 請(qǐng)求的同學(xué)應(yīng)該對(duì) Vary 這個(gè)響應(yīng)頭字段并不陌生,它有什么用?

經(jīng)常抓包看 HTTP 請(qǐng)求的同學(xué)應(yīng)該對(duì) Vary 這個(gè)響應(yīng)頭字段并不陌生,它有什么用?用 PageSpeed 工具檢查頁(yè)面時(shí),經(jīng)常看到「Specify a Vary: Accept-Encoding header(請(qǐng)指定一個(gè) Vary: Accept-Encoding 標(biāo)頭)」這樣的建議,為什么要這樣做?本文記錄我對(duì) Vary 的一些研究,其中就包含這些問(wèn)題的答案。

HTTP 內(nèi)容協(xié)商

要了解 Vary 的作用,先得了解 HTTP 的內(nèi)容協(xié)商機(jī)制。有時(shí)候,同一個(gè) URL 可以提供多份不同的文檔,這就要求服務(wù)端和客戶端之間有一個(gè)選擇最合適版本的機(jī)制,這就是內(nèi)容協(xié)商。

協(xié)商方式有兩種,一種是服務(wù)端把文檔可用版本列表發(fā)給客戶端讓用戶選,這可以使用 300 Multiple Choices 狀態(tài)碼來(lái)實(shí)現(xiàn)。這種方案有不少問(wèn)題,首先多一次網(wǎng)絡(luò)往返;其次服務(wù)端同一文檔的某些版本可能是為擁有某些技術(shù)特征的客戶端準(zhǔn)備的,而普通用戶不一定了解這些細(xì)節(jié)。舉個(gè)例子,服務(wù)端通常可以將靜態(tài)資源輸出為壓縮和未壓縮兩個(gè)版本,壓縮版顯然是為支持壓縮的客戶端而準(zhǔn)備的,但如果讓普通用戶選,很可能選擇錯(cuò)誤的版本。

所以 HTTP 的內(nèi)容協(xié)商通常使用另外一種方案:服務(wù)端根據(jù)客戶端發(fā)送的請(qǐng)求頭中某些字段自動(dòng)發(fā)送最合適的版本。可以用于這個(gè)機(jī)制的請(qǐng)求頭字段又分兩種:內(nèi)容協(xié)商專用字段(Accept 字段)、其他字段。

首先來(lái)看 Accept 字段,詳見(jiàn)下表:

請(qǐng)求頭字段 說(shuō)明 響應(yīng)頭字段
Accept 告知服務(wù)器發(fā)送何種媒體類型 Content-Type
Accept-Language 告知服務(wù)器發(fā)送何種語(yǔ)言 Content-Language
Accept-Charset 告知服務(wù)器發(fā)送何種字符集 Content-Type
Accept-Encoding 告知服務(wù)器采用何種壓縮方式 Content-Encoding

例如客戶端發(fā)送以下請(qǐng)求頭:

Accept:*/*
Accept-Encoding:gzip,deflate,sdch
Accept-Language:zh-CN,en-US;q=0.8,en;q=0.6

表示它可以接受任何 MIME 類型的資源;支持采用 gzip、deflate 或 sdch 壓縮過(guò)的資源;可以接受 zh-CN、en-US 和 en 三種語(yǔ)言,并且 zh-CN 的權(quán)重***(q 取值 0 - 1,***為 1,***為 0,默認(rèn)為 1),服務(wù)端應(yīng)該優(yōu)先返回語(yǔ)言等于 zh-CN 的版本。

瀏覽器的響應(yīng)頭可能是這樣的:

Content-Type: text/javascript
Content-Encoding: gzip

表示這個(gè)文檔確切的 MIME 類型是 text/javascript;文檔內(nèi)容進(jìn)行了 gzip 壓縮;響應(yīng)頭沒(méi)有 Content-Language 字段,通常說(shuō)明返回版本的語(yǔ)言正好是請(qǐng)求頭 Accept-Language 中權(quán)重***的那個(gè)。

有時(shí)候,上面四個(gè) Accept 字段并不夠用,例如要針對(duì)特定瀏覽器如 IE6 輸出不一樣的內(nèi)容,就需要用到請(qǐng)求頭中的 User-Agent 字段。類似的,請(qǐng)求頭中的 Cookie 也可能被服務(wù)端用做輸出差異化內(nèi)容的依據(jù)。

由于客戶端和服務(wù)端之間可能存在一個(gè)或多個(gè)中間實(shí)體(如緩存服務(wù)器),而緩存服務(wù)最基本的要求是給用戶返回正確的文檔。如果服務(wù)端根據(jù)不同 User-Agent 返回不同內(nèi)容,而緩存服務(wù)器把 IE6 用戶的響應(yīng)緩存下來(lái),并返回給使用其他瀏覽器的用戶,肯定會(huì)出問(wèn)題 。

所以 HTTP 協(xié)議規(guī)定,如果服務(wù)端提供的內(nèi)容取決于 User-Agent 這樣「常規(guī) Accept 協(xié)商字段之外」的請(qǐng)求頭字段,那么響應(yīng)頭中必須包含 Vary 字段,且 Vary 的內(nèi)容必須包含 User-Agent。同理,如果服務(wù)端同時(shí)使用請(qǐng)求頭中 User-Agent 和 Cookie 這兩個(gè)字段來(lái)生成內(nèi)容,那么響應(yīng)中的 Vary 字段看上去應(yīng)該是這樣的:

Vary: User-Agent, Cookie

也就是說(shuō) Vary 字段用于列出一個(gè)響應(yīng)字段列表,告訴緩存服務(wù)器遇到同一個(gè) URL 對(duì)應(yīng)著不同版本文檔的情況時(shí),如何緩存和篩選合適的版本。

有 BUG 的緩存服務(wù)

再來(lái)看 PageSpeed 的「Specify a Vary: Accept-Encoding header」這個(gè)提示,按照上面的說(shuō)明,Accept-Encoding 屬于內(nèi)容協(xié)商專用字段,服務(wù)端只需要在響應(yīng)頭中增加 Content-Encoding 字段,用來(lái)指明內(nèi)容壓縮格式;或者不輸出 Content-Encoding 表明內(nèi)容未經(jīng)過(guò)壓縮就可以了。而緩存服務(wù)器,應(yīng)該針對(duì)不同的 Content-Encoding 緩存不同內(nèi)容,再根據(jù)具體請(qǐng)求中的 Accept-Encoding 字段返回最合適的版本。

但是有些實(shí)現(xiàn)得有 BUG 的緩存服務(wù)器,會(huì)忽略響應(yīng)頭中的 Content-Encoding,從而可能給不支持壓縮的客戶端返回緩存的壓縮版本。有兩個(gè)方案可以避免這種情況發(fā)生:

將響應(yīng)頭中的 Cache-Control 字段設(shè)為 private,告訴中間實(shí)體不要緩存它;

增加 Vary: Accept-Encoding 響應(yīng)頭,明確告知緩存服務(wù)器按照 Accept-Encoding 字段的內(nèi)容,分別緩存不同的版本;

通常為了更好的利用中間實(shí)體的緩存功能,我們都用第二種方案。

對(duì)于 css、js 這樣的靜態(tài)資源,只要客戶端支持 gzip,服務(wù)端應(yīng)該總是啟用它;同時(shí)為了避免有 BUG 的緩存服務(wù)器給用戶返回錯(cuò)誤的版本,還應(yīng)該輸出 Vary: Accept-Encoding。

Nginx 和 SPDY

通常,上面說(shuō)的這些工作,Web Server 都可以幫我們搞定。對(duì)于 Nginx 來(lái)說(shuō),下面這個(gè)配置可以自動(dòng)給啟用了 gzip 的響應(yīng)加上 Vary: Accept-Encoding:

gzip_vary on;

#p#

用 curl 驗(yàn)證我博客的 js 文件,響應(yīng)頭如下:

jerry@www:~$ curl --head https://imququ.com/.../xx.js
HTTP/1.1 200 OK
Server: nginx
Date: Tue, 31 Dec 2013 16:34:48 GMT
Content-Type: application/x-javascript
Content-Length: 66748
Last-Modified: Tue, 31 Dec 2013 14:30:52 GMT
Connection: keep-alive
Vary: Accept-Encoding
ETag: "52c2d51c-104bc"
Expires: Fri, 29 Dec 2023 16:34:48 GMT
Cache-Control: max-age=315360000
Strict-Transport-Security: max-age=31536000
Accept-Ranges: bytes

可以看到,服務(wù)端正確輸出了「Vary: Accept-Encoding」,一切正常。

但是用 Chrome 自帶抓包工具看下,這個(gè)響應(yīng)頭卻是這樣:

HTTP/1.1 200 OK
cache-control: max-age=315360000
content-encoding: gzip
content-type: application/x-javascript
date: Tue, 31 Dec 2013 16:35:27 GMT
expires: Fri, 29 Dec 2023 16:35:27 GMT
last-modified: Tue, 31 Dec 2013 14:30:52 GMT
server: nginx
status: 200
strict-transport-security: max-age=31536000
version: HTTP/1.1

我的博客支持 SPDY/2 協(xié)議,用 Chrome 訪問(wèn)我博客會(huì)走 SPDY,所以上面的響應(yīng)頭看上有點(diǎn)不同尋常,例如字段名都變成了小寫;多了 status、version 等字段,這些變化下次專門介紹(注:見(jiàn)。神奇的是盡管服務(wù)端沒(méi)任何變化,但響應(yīng)中的 Vary: Accept-Encoding 卻不見(jiàn)了。

SPDY 規(guī)定客戶端必須支持壓縮,這意味著 SPDY 服務(wù)器可以直接啟用壓縮而不用關(guān)心請(qǐng)求頭中的 Accept-Encoding 字段。下面這段來(lái)自 Nginx 支持的 SPDY/2 協(xié)議:

User-agents are expected to support gzip and deflate compression. Regardless of the Accept-Encoding sent by the user-agent, the server may select gzip or deflate encoding at any time. [via]

于是,對(duì)于支持 SPDY 的客戶端來(lái)說(shuō),Vary: Accept-Encoding 沒(méi)有用途,Nginx 選擇直接去掉它,可以節(jié)省一點(diǎn)流量。curl 或其他不支持 SPDY 協(xié)議的客戶端還是走 HTTP 協(xié)議,所以看到的響應(yīng)頭是常規(guī)的。

Nginx 的這個(gè)做法是否合適一直有爭(zhēng)論,實(shí)際上并不是所有支持 SPDY 的 Web Server 都會(huì)這么做。例如即使通過(guò) SPDY 協(xié)議訪問(wèn) Google 首頁(yè)的 js 文件,依然可以看到 vary: Accept-Encoding:

HTTP/1.1 200 OK
status: 200 OK
version: HTTP/1.1
age: 25762
alternate-protocol: 443:quic
cache-control: public, max-age=31536000
content-encoding: gzip
content-length: 154614
content-type: text/javascript; charset=UTF-8
date: Tue, 31 Dec 2013 23:23:51 GMT
expires: Wed, 31 Dec 2014 23:23:51 GMT
last-modified: Mon, 16 Dec 2013 21:54:35 GMT
server: sffe
vary: Accept-Encoding
x-content-type-options: nosniff
x-xss-protection: 1; mode=block

另外,現(xiàn)階段 Chrome 和 Firefox 都支持 SPDY 協(xié)議,但 PageSpeed Chrome 版和 Firefox 版都沒(méi)有針對(duì) SPDY 協(xié)議做特別處理,所以用它們測(cè)試我的博客,還是會(huì)提示「Specify a Vary: Accept-Encoding header」,這有點(diǎn)讓人哭笑不得。不過(guò) PageSpeed 在線版 已經(jīng)更新規(guī)則,估計(jì)擴(kuò)展版也快了。如果你有潔癖,可以在 Nginx 配置里加上「add_header vary accept-encoding;」手動(dòng)輸出 Vary 響應(yīng)頭。

責(zé)任編輯:何妍 來(lái)源: Jerry Qu的小站
相關(guān)推薦

2015-09-16 13:11:52

Http網(wǎng)絡(luò)協(xié)議Proxy-Conne

2015-09-17 10:29:07

Http網(wǎng)絡(luò)協(xié)議X-Forwarded

2015-09-29 14:01:45

SPDY網(wǎng)絡(luò)協(xié)議響應(yīng)頭網(wǎng)絡(luò)協(xié)議

2015-09-15 13:48:01

網(wǎng)絡(luò)協(xié)議HTTP Client

2010-07-06 16:19:02

協(xié)議封裝

2010-06-08 11:25:01

HTTP協(xié)議通用頭域

2010-06-21 15:06:45

AMF協(xié)議

2015-09-15 15:20:35

2010-06-21 17:55:24

RIP協(xié)議

2010-07-08 13:23:14

SAN路由協(xié)議

2010-07-08 14:25:12

HART協(xié)議

2021-01-11 05:40:18

HTTPHTTP 協(xié)議網(wǎng)絡(luò)技術(shù)

2018-07-12 15:30:03

HTTP緩存機(jī)制

2015-09-06 13:40:02

HTTP網(wǎng)絡(luò)協(xié)議

2015-09-07 13:52:04

2015-09-06 10:54:29

HTTP網(wǎng)絡(luò)協(xié)議

2015-09-08 10:06:15

2015-10-20 09:46:33

HTTP網(wǎng)絡(luò)協(xié)議

2018-07-23 15:28:29

HTTPCookieHeader

2018-06-27 15:14:31

HTTP編碼內(nèi)容
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 日韩精品久久一区二区三区 | 国产高清免费视频 | 99re热精品视频国产免费 | 精品一区二区三区四区五区 | 欧美一级α片 | 国产视频中文字幕在线观看 | 欧美日韩在线一区二区 | www.一区二区 | 国产一区二区视频在线观看 | 国产精品日韩欧美一区二区三区 | 国产精品视频久久久久久 | 国产精品99一区二区 | www.国产91| 男人天堂视频在线观看 | 欧美日韩一区精品 | 精品一区国产 | 国产一区二区三区在线 | 男女午夜激情视频 | 美女啪啪国产 | 美女日批免费视频 | 欧美激情精品久久久久久变态 | 亚洲色图婷婷 | 超碰免费在线观看 | 国产高清视频在线播放 | 欧美日韩在线一区二区 | 精品91视频 | 日韩国产在线 | 欧美成人在线影院 | 日韩欧美一级精品久久 | 成人3d动漫一区二区三区91 | 一区二区小视频 | 91免费观看在线 | 久久精品无码一区二区三区 | 国产精品久久久久久久久久妞妞 | 在线午夜 | 国产精品午夜电影 | 亚洲综合无码一区二区 | 欧美在线视频一区二区 | 久久高潮 | 天天干在线播放 | 亚洲一区二区三区福利 |