2014-01-30 56 views
1

我一直在嘗試刷新我對HTTP/1.1緩存的理解 - 我發現我必須每隔一段時間做一次,因爲似乎有太多可能的組合讓我的大腦可靠地記住。瀏覽器何時刷新陳舊的緩存條目?

我就把它作爲鑑於Expiresmax-age高速緩存控制指令是使用瀏覽器作爲提示,不是鐵定的規律:如果一個緩存條目是陳舊(比其最大年齡大),瀏覽器可以驗證它。

一位同事和我有一點關於這一點,他強迫我閱讀RFC,我覺得這有點嚴厲,但證明他是完全正確的:如果我的理解正確,客戶端不允許使用一個他們知道陳舊的緩存條目。換句話說:如果文檔指定了max-age緩存標頭,並且沒有其他指令(如must-validate)影響緩存行爲,並且該文檔的緩存條目變得陳舊,那麼瀏覽器將始終重新驗證它。

這是完全清晰的邏輯,並把這樣的說法來休息,我開始由具有服務器憑經驗確認服務測試JavaScript文件具有以下標題:

< HTTP/1.1 200 OK 
< Content-Type: application/x-javascript; charset=UTF-8 
< Cache-Control: public, max-age=30 
< Date: Thu, 30 Jan 2014 22:11:28 GMT 
< Accept-Ranges: bytes 
< Server: testServer/1.0 
< Vary: Accept-Encoding 
< Transfer-Encoding: chunked 

這個JavaScript文件包含在文檔的<head>中通過<script>元素託管在同一服務器上的HTML頁面中。在HTML頁面送達下列緩存控制標題:

Cache-Control: no-cache, must-revalidate, no-store, max-age=0 

加載HTML網頁後,我經歷到不同的頁面點擊,等待5分鐘,好措施,並點擊一個鏈接就回到原來的頁面,監視所有HTTP請求 - 並且測試文件從未被請求過。這與Firefox和Safari的最新版本一致。

這有點冗長,但我的問題的要點是:我的測試似乎表明,主流瀏覽器不尊重RFC並且不會重新驗證陳舊的緩存條目。我誤解了RFC嗎?同樣可能,我是否弄錯了我的測試,並且有人能證明他們錯了嗎?或者瀏覽器真的不尊重max-age緩存指令?

+0

'HTTP/1.0'或'HTTP/1.1'?我和你在一起,順便說一句,我不認爲瀏覽器會遵從RFC中的MUST要求...... – Wrikken

+0

好的,謝謝。我編輯了這個問題來指定'HTTP/1.1'。 –

+0

你如何讓瀏覽器請求這個文件,你是否將它用作HTML文檔中腳本標記的源代碼?該文檔提供了哪些緩存標題? 「導航離開並回來」是什麼意思,(如何)刷新包含頁面? – CodeCaster

回答

0

我無法重現您的問題。我曾嘗試使用ASP.NET MVC,用下面的代碼:

public ActionResult Index() 
{ 
    Response.AddHeader("Cache-Control", 
         "no-cache, must-revalidate, no-store, max-age=0"); 
    return View(); 
} 

public ActionResult JavaScript() 
{ 
    Response.AddHeader("Cache-Control", "public, max-age=30"); 
    return View(); 
} 

public ActionResult Page2() 
{ 
    return View(); 
} 

第一個動作返回索引頁(僅適用於相關的標題):

HTTP/1.1 200 OK 
Cache-Control: no-cache, no-store, must-revalidate, max-age=0 
Pragma: no-cache 
Expires: -1 
Vary: Accept-Encoding 
Content-Length: 182 


<html> 
    <head> 
     <script src="/Home/JavaScript" type="text/javascript"></script> 
    </head> 
    <body> 
     <a href="/Home/Page2">Page 2</a> 
    </body> 
</html> 

JavaScript的返回是這樣的:

HTTP/1.1 200 OK 
Cache-Control: public, max-age=30 
Vary: Accept-Encoding 
Content-Length: 24 


document.write('Foo'); 

Page2只是包含一個鏈接回家。

現在,當我使用Internet Explorer 11,Chrome 32版本或Firefox 26,我看到了以下行爲:

  • 在第一次請求/,索引文件要求,以及JavaScript文件,並且如上所示返回它們,如Fiddler所驗證的那樣。
  • 當我點擊「Page 2」鏈接時,只請求第2頁,因爲它不包含任何內容,只不過鏈接回頁面1.現在當我點擊第2頁的「Home」鏈接時30秒,JS文件是而不是在任何瀏覽器中再次請求。
  • 當我在頁面2上等待一段時間(> 30秒)然後單擊「Home」鏈接時,所有三個瀏覽器中要求的JS文件

然而,當我從第2頁在任何瀏覽器的任何一段時間後單擊後退按鈕(或者大於或小於30秒),索引文件是永遠,但JS文件永遠在任何瀏覽器中再次請求

它需要刷新(F5)或導航離開和返回,再次點擊「頁面2」,然後再次點擊「主頁」,以使瀏覽器在JS文件過期後執行新的請求。

+0

您的第一個發現(JS在被鏈接到'/'後的30秒後重新加載)與我自己的不匹配,但我傾向於相信您的結果比我的更多:它們符合RFC所說的應該發生的事情。另一方面,在歷史回顧中沒有被重新加載的事實似乎明顯違反了RFC。你似乎不同意,我會對你的理由感興趣。 –

+0

@Nicolas我只是報告我所看到的。 :-)奇怪的是,您的瀏覽器似乎顯示相同標題的不同行爲。我希望後端單擊也可以啓動JS文件的重新加載,因爲瀏覽器知道它是陳舊的,而且它似乎對索引文檔也是如此。我想,還需要更多的試驗(或閱讀瀏覽器的問題追蹤器,郵件列表或源代碼)來了解爲什麼會發生這種情況。除非有人更有見識,否則不要接受這個答案。 – CodeCaster

+1

經過三重檢查我的測試後,你的結果是正確的:通過鏈接回到根頁面*將*導致陳舊的條目被重新驗證,通過瀏覽器的歷史不會回到它。經過一番挖掘,我發現RFC的第[13.3]節(http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13.13)解釋了爲什麼這是預期的行爲。 –

1

經過對@CodeCaster的大量挖掘和幫助之後,對這個問題的規範回答是瀏覽器確實看起來尊重RFC:過時的緩存條目總是被重新驗證,除非在特定情況下直接訪問它們或通過瀏覽器的歷史間接。在這種情況下,RFC的13.3部分適用:

歷史機制和高速緩存不同。特別是歷史機制不應該試圖顯示資源當前狀態的語義透明視圖。相反,歷史機制意味着準確顯示用戶在檢索資源時看到的內容。