2009-12-29 223 views
82

我使用PHP來生成動態網頁。如以下教程所述(請參閱下面的鏈接),當$ _SERVER ['HTTP_ACCEPT']允許時,MIME類型的XHTML文檔應該是「application/xhtml + xml」。由於您可以使用2種不同的MIME(「application/xhtml + xml」和「text/html」)提供相同的頁面,因此您應該將「Vary」HTTP標頭設置爲「Accept」。這將有助於緩存代理。「Vary:Accept」HTTP頭的功能是什麼?

鏈接: http://keystonewebsites.com/articles/mime_type.php

現在我不知道的寓意: 頭( '有所不同:接受'); 我真的不知道什麼「有所不同:接受」將精確地做......

我發現的唯一解釋是:

的Content-Type頭後,因人而異 頭中發送到(如果我正確理解它 )告訴中間緩存 像代理服務器一樣,文檔的內容 根據請求文檔的客戶端 的功能而變化,具體取決於 。 http://www.456bereastreet.com/archive/200408/content_negotiation/

任何人都可以給我這個頭的「真實」的解釋(與價值)。我想我明白了諸如: 有所不同:接受編碼 凡代理緩存可以基於網頁的編碼服務,但我不明白: 各不相同:接受

+1

坦率地說 - 不要打擾。撇開該網站實施中的缺陷,唯一一次從XML內容類型服務中獲得好處的時候是,當你做一些無法在text/html中完成的事情 - 並且如果你在做所有事情正在轉換Doctype和xmlns,那麼你不會去做那些事情。堅持text/html。對於這個問題,你可能會堅持使用HTML 4.01。 – Quentin 2009-12-29 17:22:42

+0

是的,我明白這一點,我認爲像這樣的「問題」在Web開發中經常出現。感謝規範/ RFC中的「應該」! – AlexV 2009-12-29 18:22:33

+2

在考慮使用VARY之前,您應該閱讀以下內容:http://blogs.msdn.com/ieinternals/archive/2009/06/17/Vary-Header-Prevents-Caching-in-IE.aspx。 – EricLaw 2010-01-05 03:44:55

回答

85
  • cache-control頭部是HTTP服務器告訴緩存代理響應「新鮮」的主要機制。 (即,如何/如果長時間將響應存儲在緩存中)

  • 在某些情況下,cache-control指令是不夠的。來自HTTP工作組的討論被存檔here,,其描述了僅隨語言改變的頁面。這是而不是正確使用情況的變化標題,但上下文對於我們的討論是有價值的。 (雖然我相信Vary標頭可以解決這個問題在這種情況下,有一個更好的辦法。)在這個頁面:

Vary是嚴格的情況下,這是絕望或過於複雜的代理來複制服務器將執行的操作。

一個人爲的例子:

你的HTTP服務器有一個大的着陸頁。您有兩個略有不同的頁面,並且具有相同的URL,具體取決於用戶之前是否在那裏。您根據Cookie區分請求和用戶的「訪問計數」。但是,由於您的服務器的着陸頁太大,您希望中​​介代理緩存響應,如果可能的話。

URL,Last-Modified和Cache-Control標頭不足以將此洞察信息提供給緩存代理,但如果添加Vary: Cookie,則緩存引擎會將Cookie標頭添加到其緩存決策中。

最後,對於小流量,動態網站 - 我總是發現簡單的Cache-Control: no-cache, no-storePragma: no-cache就足夠了。

編輯 - 更準確地回答你的問題:HTTP請求頭'Accept'定義了客戶端可以處理的內容類型。如果您在同一個網址上有兩個相同內容的副本,只有內容類型不同,則使用Vary: Accept可能是適當的。

更新12年9月11日:

我包括已經出現了意見,因爲此評論最初發布幾個鏈接。它們都是用Vary實現的真實案例(和問題)的絕佳資源:Accept;如果你正在閱讀這個答案,你也需要閱讀這些鏈接。

第一個來自傑出的EricLaw,關於Internet Explorer的Vary頭部行爲以及它向開發人員提出的一些挑戰:Vary Header Prevents Caching in IE。簡而言之,IE(IE9之前)不會緩存使用Vary頭的任何內容,因爲請求緩存不包含HTTP請求頭。 EricLaw(Eric Lawrence在現實世界中)是IE團隊的項目經理。

第二個來自Eran Medan,並且正在討論Chrome中與Vary相關的意外行爲:Backing doesn't handle Vary header correctly。這與IE的行爲有關,除了Chrome開發者採取了不同的方法 - 儘管它似乎並不是一個有意的選擇。

+3

在Chrome瀏覽器按鈕中注意這一點,對這個錯誤(現在是由於某種原因wontfix)有點火焰戰爭http://code.google.com/p/chromium/issues/detail? id = 94369 – 2012-09-07 02:39:44

+5

@EranMedan Chrome bug已經修復。 – 2014-05-05 21:43:23

54

Vary: Accept只是表示響應是基於請求中的Accept標頭生成的。具有不同Accept標頭的請求可能會得到不同的響應。

(你可以看到鏈接的PHP代碼看$HTTP_ACCEPT。這就是Accept請求頭的值。)

要HTTP緩存,這意味着響應必須格外小心被緩存。只有在後面的請求Accept標頭完全相同時纔有效。

現在,這隻有在頁面緩存在第一位時纔有意義。默認情況下,PHP頁面不是。 PHP頁面可以通過發送某些標題(例如Expires)將輸出標記爲可緩存。但是是否以及如何去做是一個不同的問題。

+0

它是「可能得到」還是應該得到? – Pacerier 2011-09-25 22:00:07

+6

@Pacerier「可能會得到」是正確的。 'Vary:Accept'並不意味着每一個可能不同的'Accept'頭部值都會產生不同且獨特的響應。這隻意味着不同的'Accept'頭*可能會產生不同的響應。 – 2011-09-28 21:29:52

2

實際上有很多新功能即將推出(並且已經在Chrome中),使得Vary標頭非常有用。例如,考慮Client Hinting。當與圖像結合使用,例如,客戶機提示允許服務器優化資源諸如取決於圖像:

  • 圖片寬度
  • 視口寬度
  • 編碼的由瀏覽器支持的類型(認爲WebP的)
  • 下行鏈路(網絡基本上速度)

所以它支持的那些特徵將設置Vary報頭中的服務器,以指示。

Chrome通過將「image/webp」設置爲每個請求的Vary標題的一部分來宣傳WebP支持。因此,如果瀏覽器支持它,服務器可能會將圖像重寫爲WebP,因此代理需要檢查標題以便不緩存WebP圖像,然後將其提供給不支持WebP的瀏覽器。顯然,如果你的服務器不這樣做,那就沒關係了。如此以來,服務器的響應於Accept請求頭而變化,該響應必須包含以免混淆代理:

Vary: Accept 

另一個例子是圖像的寬度。在移動瀏覽器上,Width標題對於響應式圖像而言可能相當小,與從桌面瀏覽器查看時相比較。因此,在這種情況下,Width將被添加到Vary標頭對於代理不緩存小型移動版本並將其提供給桌面瀏覽器至關重要,反之亦然。在這種情況下,頭部可能包括:

Vary: Accept, Width 

或在一臺服務器支持的所有客戶端提示規格的情況下,標題會是這樣的:

Vary: Accept, DPR, Width, Save-Data, Downlink