?
本文檔使用 PHP中文網(wǎng)手冊 發(fā)布
在HTTP中,內(nèi)容協(xié)商是用于在相同URI處為資源提供不同表示的機制,以便用戶代理可以指定哪一個最適合用戶(例如,文檔的哪種語言,哪種圖像格式或哪些內(nèi)容編碼)。
一個特定的文檔被稱為資源。當客戶想要獲得它時,它會使用它的URL來請求它。服務器使用此URL來選擇它提供的變體之一 - 每個變體稱為表示 - 并將此特定表示形式返回給客戶機。整體資源以及每個表示都有一個特定的URL。在調(diào)用資源時如何選擇特定的表示形式取決于內(nèi)容協(xié)商,并且客戶端和服務器之間有多種協(xié)商方式。
通過以下兩種機制中的一種來確定最適合的表示:
客戶端的特定HTTP頭(服務器驅(qū)動的協(xié)商或主動協(xié)商),這是協(xié)商特定種類資源的標準方式。
服務器(代理驅(qū)動的協(xié)商或反應式協(xié)商)提供的300
(多選)或406
(不可接受的)HTTP響應代碼,用作后備機制。
多年來,已經(jīng)提出了其他內(nèi)容協(xié)商提議,如透明內(nèi)容協(xié)商和Alternates
標題。他們未能獲得牽引力而被拋棄。
在服務器驅(qū)動的內(nèi)容協(xié)商或主動式內(nèi)容協(xié)商中,瀏覽器(或任何其他類型的用戶代理)會發(fā)送多個HTTP標頭以及URL。這些標題描述了用戶的首選。服務器使用它們作為提示,并且內(nèi)部算法選擇向客戶端提供最佳內(nèi)容。該算法是特定于服務器的,并未在標準中定義。例如,請參閱Apache 2.2協(xié)商算法。
HTTP / 1.1標準定義了啟動服務器驅(qū)動的協(xié)商(標準報頭的列表Accept
,Accept-Charset
,Accept-Encoding
,Accept-Language
)。雖然嚴格來說User-Agent
不在此列表中,但它有時也用于發(fā)送所請求資源的特定表示,盡管這不被認為是一種好的做法。服務器使用Vary
頭來指示它實際用于內(nèi)容協(xié)商的頭(或更確切地說是關(guān)聯(lián)的響應頭),以便緩存可以最佳地工作。
除此之外,還有一個實驗性的建議是在可用標題列表中添加更多標題,稱為客戶端提示??蛻舳颂崾就ㄖ脩舸磉\行的設(shè)備類型(例如,如果它是臺式計算機或移動設(shè)備)。
即使服務器驅(qū)動的內(nèi)容協(xié)商是就資源的特定表示達成一致的最常見方式,但它有幾個缺點:
服務器不具有瀏覽器的全部知識。即使使用客戶端提示擴展,它也不完全了解瀏覽器的功能。與客戶做出選擇的被動內(nèi)容協(xié)商不同,服務器選擇總是有些隨意。
客戶端的信息非常詳細(HTTP / 2頭壓縮緩解了這個問題)和隱私風險(HTTP指紋)
隨著給定資源的多個表示被發(fā)送,共享緩存效率較低,服務器實現(xiàn)更為復雜。
Accept
頭該Accept
標題列出了MIME類型的媒體資源代理愿意處理。它是以逗號分隔的MIME類型列表,每個列表都與質(zhì)量因子相結(jié)合,該參數(shù)指示不同MIME類型之間的相對偏好程度。
Accept
頭是由瀏覽器,或任何其它用戶代理限定,并且可以根據(jù)環(huán)境而變化,像取HTML頁面或圖像,視頻,或腳本:提取在輸入的地址的文檔時它是不同桿或元件經(jīng)由連接<img>
,<video>
或<audio>
元件。瀏覽器可以自由使用他們認為最合適的標題的值; 常見瀏覽器默認值的詳盡列表可用。
Accept-CH
頭這是名為Client Hints的實驗性技術(shù)的一部分,目前僅在Chrome 46及更高版本中實施
實驗Accept-CH
列出了服務器可用于選擇適當響應的配置數(shù)據(jù)。有效值是:
值 | 含義 |
---|---|
DPR | 指示客戶端的設(shè)備像素比率。 |
視口寬度 | 指示CSS像素中的布局視口寬度。 |
寬度 | 指示物理像素中的資源寬度(換句話說,是圖像的固有大?。?/p> |
Accept-Charset
頭Accept-Charset
標題指示到什么樣的字符編碼由用戶代理理解服務器。傳統(tǒng)上,它針對瀏覽器的每個區(qū)域設(shè)置為不同的值,例如ISO-8859-1,utf-8;q=0.7,*;q=0.7
西歐語言區(qū)域設(shè)置。
UTF-8現(xiàn)在得到了很好的支持,成為字符編碼的首選方式,并通過減少基于配置的熵來保證更好的隱私,大多數(shù)瀏覽器都忽略了Accept-Charset
標題:Internet Explorer 8,Safari 5,Opera 11和Firefox 10已經(jīng)放棄這個標題。
Accept-Encoding
頭Accept-Encoding
報頭定義內(nèi)容編碼的可接受的(支持的壓縮)。該值是br, gzip;q=0.8
指示編碼值的優(yōu)先級的q因子列表(例如:)。默認值identity
是最低優(yōu)先級(除非另有聲明)。
壓縮HTTP消息是提高Web站點性能的最重要方式之一,它縮小了傳輸數(shù)據(jù)的大小并更好地利用了可用帶寬; 瀏覽器總是發(fā)送這個頭文件,服務器應該被配置為遵守并使用壓縮。
Accept-Language
頭所述Accept-Language
報頭用于指示所述用戶的語言偏好。它是一個包含質(zhì)量因素的值列表(如:"de, en;q=0.7
“)。默認值通常根據(jù)用戶代理圖形界面的語言設(shè)置,但大多數(shù)瀏覽器允許設(shè)置不同的語言首選項。
由于基于配置的熵增加,可以使用修改后的值來為用戶指紋,不建議對其進行更改,并且網(wǎng)站不能相信此值以反映用戶的實際愿望。網(wǎng)站設(shè)計人員不能通過使用通過此標頭進行語言檢測而過于熱心,因為這會導致糟糕的用戶體驗:
他們應該始終提供一種方法來克服服務器選擇的語言,例如通過在網(wǎng)站上提供語言菜單。大多數(shù)用戶代理為Accept-Language
標題提供一個默認值,根據(jù)用戶界面語言進行調(diào)整,最終用戶通常不會對其進行修改,或者不知道如何修改,或者無法完成,就像在網(wǎng)吧中一樣。
一旦用戶重寫了服務器選擇的語言,站點就不應該再使用語言檢測,并應該堅持使用明確選擇的語言。換句話說,只有網(wǎng)站的入口頁面應該使用這個頭文件選擇適當?shù)恼Z言。
User-Agent
頭雖然這個標題有合法的用途來選擇內(nèi)容,但依賴它來定義用戶代理支持哪些功能被認為是不好的做法。
User-Agent
報頭標識瀏覽器發(fā)送請求。該字符串可能包含空格分隔的產(chǎn)品標記和注釋列表。
一個產(chǎn)品標記 是一個后面是“ /
”和版本號一樣Firefox/4.0.1
的名字。用戶代理想要的可能有很多。一個注釋是括號分隔的一個任意字符串。顯然括號不能用在那個字符串中。評論的內(nèi)部格式不是由標準定義的,盡管多個瀏覽器在其中放置了幾個標記,以' ;
' 分隔。
Vary
響應報頭Accept-*
與客戶端發(fā)送的先前標題相反,Vary
HTTP標題是由Web服務器在其響應中發(fā)送的。它表示服務器驅(qū)動的內(nèi)容協(xié)商階段服務器使用的標頭列表。標題是需要的,以便通知緩存的決策標準,以便它可以重現(xiàn)它,允許緩存功能,同時防止向用戶提供錯誤的內(nèi)容。
' *
' 的特殊值意味著服務器驅(qū)動的內(nèi)容協(xié)商也使用信息中未傳送的信息來選擇適當?shù)膬?nèi)容。
Vary
在HTTP的1.1版本中加入報頭和是必要的,以便允許高速緩存以適當?shù)毓ぷ鳌榱伺c服務器驅(qū)動的內(nèi)容協(xié)商一起工作,高速緩存需要知道服務器使用哪個標準來選擇傳輸?shù)膬?nèi)容。這樣,緩存就可以重播算法,并能夠直接提供可接受的內(nèi)容,而無需向服務器提出更多請求。顯然,通配符' *
'阻止了緩存的發(fā)生,因為緩存不知道它背后是什么元素。
服務器驅(qū)動的協(xié)商有一些缺點:它不能很好地擴展。談判中使用的每個功能都有一個標題。如果您想使用屏幕尺寸,分辨率或其他尺寸,則必須創(chuàng)建新的HTTP標頭。發(fā)送標題必須在每個請求上完成。這并不是問題很少,只有很少的標題,但隨著它們的最終乘法,消息大小會導致性能下降。發(fā)送的報頭越精確,發(fā)送的熵就越多,允許更多的HTTP指紋識別和相應的隱私問題。
從HTTP開始,協(xié)議允許另一種協(xié)商類型:代理驅(qū)動協(xié)商或反應式協(xié)商。在這個協(xié)商中,當面對不明確的請求時,服務器發(fā)送一個包含指向可用替代資源鏈接的頁面。用戶被呈現(xiàn)資源并選擇要使用的資源。
不幸的是,HTTP標準沒有指定允許在可用資源之間進行選擇的頁面格式,這阻止了輕松自動化該過程。除了回到服務器驅(qū)動的協(xié)商之外,這種方法幾乎總是與腳本一起使用,尤其是在JavaScript重定向的情況下:在檢查協(xié)商標準后,腳本執(zhí)行重定向。第二個問題是需要多一個請求才能獲取真實資源,從而減慢了用戶對資源的可用性。