【问题标题】:Chrome doesn't send "If-Modified-Since"Chrome 不发送“If-Modified-Since”
【发布时间】:2012-04-19 21:43:45
【问题描述】:

我希望浏览器始终添加(第一次除外)“If-Modified-Since”请求标头以避免不必要的流量。

响应头是:

Accept-Ranges:bytes
Cache-Control:max-age=0, must-revalidate
Connection:Keep-Alive
Content-Length:2683
Content-Type:text/html; charset=UTF-8
Date:Thu, 05 Apr 2012 13:06:19 GMT
Keep-Alive:timeout=15, max=497
Last-Modified:Thu, 05 Apr 2012 13:05:11 GMT
Server:Apache/2.2.21 (Red Hat)

FF 11 和 IE 9 都发送“If-Modified-Since”并得到 304 作为响应,但 Chrome 18 没有并得到 200。

为什么?如何强制 Chrome 发送“If-Modified-Since”标头? 我不知道它是否重要,但所有请求都通过 HTTPS。

【问题讨论】:

  • 归根结底,取决于浏览器和任何中间缓存,它们是否实际缓存内容(您可以控制它们是否应该)。您将无法 100% 阻止用户代理重新请求内容。
  • 我注意到 Chrome 不会发送 If-Modified-Since 标头,除非响应是 gzip'd。我不确定这是否是一种真实的模式,或者只是我尝试处理更新 JS 文件的经验。
  • 发送 Keep-Alive 有什么特别的原因吗?

标签: http if-modified-since


【解决方案1】:

我一直在关注这个问题,想分享一下我的发现。

“规则其实很简单:证书的任何错误都意味着页面不会被缓存。”

https://code.google.com/p/chromium/issues/detail?id=110649

如果您使用的是自签名证书,即使您告诉 Chrome 为其添加例外以便页面加载,该页面中的任何资源都不会被缓存,后续请求也不会有 If-Modified-从头开始。

【讨论】:

    【解决方案2】:

    我刚刚发现了这个问题,在对 Chrome 的If_Modified_Since 行为感到困惑之后,我找到了答案。

    Chrome 缓存文件的决定是基于它接收到的Expires 标头。 Expires 标头有两个主要要求:

    1. 必须采用格林威治标准时间 (GMT),并且
    2. 必须按照RFC 1123(基本上是RFC 822,四位数年份)进行格式化。

    格式如下:

    Expires: Sat, 07 Sep 2013 05:21:03 GMT
    

    例如,在 PHP 中,以下输出格式正确的标头。

    $duration = time() + 3600 // Expires in one hour.
    header("Expires: " . gmdate("D, d M Y H:i:s", $duration) . " GMT");
    

    ("GMT" 附加到字符串而不是 "e" 时区标志,因为当与 gmdate() 一起使用时,该标志将输出 RFC 1123 认为无效的 "UTC"。另请注意 PHP constants DateTime::RFC1123DATE_RFC1123 不会提供正确的格式,因为它们输出 与 GMT 小时的差异 [即 +02:00] 而不是“GMT”。 )

    请参阅W3C's date/time format specifications 了解更多信息。

    简而言之,Chrome 只会在标题遵循这种精确格式的情况下才能识别它。这与Cache-Control 标题相结合...

    header("Cache-Control: private, must-revalidate, max-age=" . $duration);
    

    ...允许我实施适当的缓存控制。一旦 Chrome 识别出这些标头,它就会开始缓存我发送给它的页面(即使是查询字符串!),它还开始发送 If_Modified_Since 标头。我将它与存储的“最后修改”日期进行比较,发回HTTP/1.1 304 Not Modified,一切正常。

    希望这可以帮助其他遇到困难的人!

    【讨论】:

    • 谢谢,GMT 时区是我没有注意到的问题 :)
    【解决方案3】:

    我注意到几乎相同的行为,我的发现是:

    • 首先,chrome 中的 200 状态指示器并不是全部事实,您还需要查看“Size Content”列。如果这显示“(来自缓存)”,则资源直接从缓存中获取,甚至没有询问它是否被修改。

    • 在请求具有 last-modified 标头的静态文件时,这种缺乏任何过期或 max-age 指示的资源缓存行为似乎适用。我注意到 chrome (ver. 22):

      1. 第一次请求文件(显然因为它不在缓存中)。
      2. 询问它是否被第二次修改(因为它在缓存中但没有新鲜的迹象)。
      3. 第三次直接使用,然后再使用(即使是新的浏览器会话)。
    • 我对这种行为有点困惑,但这是相当合理的,如果它是静态的,很久以前就被修改过,并且自上次检查以来没有改变,你可以假设它会是有效期更长(但不知道他们是如何计算的)。

    【讨论】:

    • 嗨@Albert Bertilsson 1. 第一次索要文件 ** 2. ** 3.** ,这是你的结论吗?我觉得不对,chrome缓存使用的哪个策略应该是LM-Factor,而不是你说的。如果您从谷歌官方文档中引用此内容,请通过链接,谢谢。
    • 关于你的最后一点,浏览器如何知道文件是否是静态的?
    【解决方案4】:

    我遇到了同样的问题,在 Chrome 中所有请求的状态码总是 200,在其他浏览器中是 304。

    原来我在 Devtools - 设置 - 常规页面上签入了禁用缓存(在 DevTools 打开时)。:)

    【讨论】:

      【解决方案5】:
      1. 不要在 Chrome 开发工具中禁用缓存(在“网络”标签上)。
      2. 缓存控制应该是Cache-Control: public。使用true 作为header PHP 函数的第二个参数:header("Cache-Control: public", true);

      【讨论】:

        【解决方案6】:

        我还发现,如果我打开 DevTools,Chrome(最近的 v95+)也会返回缓存的 200 响应。它甚至从不将请求发送到服务器!如果我关闭 DevTools,行为应该是正常的,并且服务器会收到预期的请求。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2018-10-23
          • 1970-01-01
          • 2012-11-27
          • 1970-01-01
          • 1970-01-01
          • 2018-01-27
          • 1970-01-01
          • 2012-01-07
          相关资源
          最近更新 更多