浏览器用什么启发式方法来缓存未明确设置为可缓存的资源?

31

13.2.2 启发式过期

由于源服务器并非总是提供明确的过期时间,HTTP缓存通常会分配启发式过期时间,采用使用其他标头值(如Last-Modified时间)来估计合理的过期时间的算法。 HTTP / 1.1规范没有提供具体的算法,但对其结果施加了最坏情况的限制。由于启发式过期时间可能会损害语义透明性,因此应谨慎使用,并鼓励源服务器尽可能提供明确的过期时间。 HTTP/1.1 RFC 2616

浏览器用于估算合理过期时间的算法是什么?
理想答案将涵盖所有主要浏览器,并提供来自源代码或官方博客文章的证据。

2
如果检测到的资源的MIME类型也起到作用,我会感到好奇。同时需要注意,在同一份RFC中还写道:“此外,如果响应确实具有最后修改时间,则启发式过期值不应超过自那个时间以来的间隔的某个分数。这个分数的典型设置可能是10%”。测试的一种方法是在服务器上放置一个没有这些标头的文件,然后在所有浏览器中进行测试,看看它们都返回什么响应,然后检查您本地的浏览器缓存是否过期。 - Anthony Hatzopoulos
如果浏览器公开了该信息。 - Anthony Hatzopoulos
5个回答

24
假设我们关心的所有浏览器都是Internet Explorer 8或更新版本(例如,IE5对缓存标头有一些可怕的行为),因此只有一个基于标准的方法可以控制缓存(在HTTP / 1.1中引入)- Cache-Control HTTP header
自1996年以来,IE一直使用HTTPS内容的“退出”策略进行缓存。自其引入以来,Chrome似乎已经对HTTPS采取了“退出”策略(即,除非告知不这样做,否则将对其进行缓存)。2011年Firefox 4(但不包括Safari)切换到了HTTPS内容的“退出”缓存。来源

建议

  1. Only use HTTP headers to control browser caching. If you decide to go against this be aware that IE only recognizes two cache control directives that are set inside HTML:

    <META HTTP-EQUIV="Pragma" CONTENT="no-cache">
    <META HTTP-EQUIV="Expires" CONTENT="-1">
    

    and seemingly only the former is useful in the HTTPS scenario. Further, there can be problems when trying to use Pragma in IE. Finally, Chrome ignores cache directives in meta tags reducing their usefulness even further.

  2. Don't use the Expires header. In modern browsers Expires is superseded by Cache-Control. Expires: 0 and Pragma: no-cache are technically invalid response headers. Yes, they have existed since the beginning but not all modern browsers (e.g. Chrome) use them and they have been superseded by Cache-Control.

  3. The Vary header is a minefield. How Vary behaves in older IEs. How Vary behaves with XHR. Finding the details out is left as an exercise to the reader - and leaves the impression it is preferable to use different URLs for different content...

  4. Allow the browser to make conditional requests by setting ETags. Etags allow a browser to do a lightweight check to see if the content has changed and it can avoid making a full request if it hasn't.

  5. Be aware some browsers are just broken and need hacks. IE 8 can have issues downloading files which it has been told not to cache.

浏览器缓存算法

参见


1
很棒的帖子,+1。只有一个更正:Pragma是HTTP/1.0标头,确实已被取代,但Expires标头是完全有效并且在所有浏览器中被接受。此外,IE <9仅适用于历史课程。 - aross
注意:Firefox ComputeFreshnessLifetime()已更改:现在对于Last-Modified启发式算法有一个一周的上限。 - Pascal Pixel Rigaux

13

来自Chromium源代码:https://code.google.com/p/chromium/codesearch#chromium/src/net/http/http_response_headers.cc&l=1082&rcl=1421094684

  if ((response_code_ == 200 || response_code_ == 203 ||
       response_code_ == 206) && !must_revalidate) {
    // TODO(darin): Implement a smarter heuristic.
    Time last_modified_value;
    if (GetLastModifiedValue(&last_modified_value)) {
      // The last-modified value can be a date in the future!
      if (last_modified_value <= date_value) {
        lifetimes.freshness = (date_value - last_modified_value) / 10;
        return lifetimes;
      }
    }
  }

6
我想知道Darin是否曾经想过他们的TODO注释会出现在Stack Overflow的答案中,:p。 - cic
我在这里有些困惑:date_valueDate字段的值吗?它看起来每次我发出请求时都会改变,是这样吗?而且它的值始终是源服务器上的日期。这是否意味着lifetimes.freshness也一直在增加(因为date_value增加但last_modified_value应该保持不变)? - yaobin

9
似乎webkit“... Safari 使用的引擎的 OS X 系统框架版本...”)使用与Chromium相同的启发式方法。
下面是从CacheValidation.cpp中提取的内容:
return (creationTime - lastModifiedValue) * 0.1;

8

4

据我最近查看的情况,Gecko 估计过期时间为 现在时间 + (现在时间 - 上次修改时间)/10


这已经不再是真的了。现在是这样的,上限为“从现在起1周”。https://bugzilla.mozilla.org/show_bug.cgi?id=277813 - aross

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接