缓存控制未返回304

问题描述

我有一个静态资产不变的网站(js,图像等)。这些资产中的每一个都设置了具有以下属性的缓存控制标头:

cache-control: public,max-age=31536000,immutable

但是,当我重新加载页面时,我仍然从服务器看到200条响应,而不是304条响应。浏览器指示正在从内存或磁盘缓存中提供资产,但仍在发出请求并下载内容。这以前曾经有用,我倾向于将其作为浏览器错误,但我不确定。

解决方法

评论中讨论的内容以及Kevin提到的内容,您似乎对conditional get的请求有误解。

您可能想回答以下问题:

1。为什么浏览器获取HTTP 200状态而不是304状态?

当浏览器加载任何文档时,对静态资源的请求将通过缓存处理程序,并且如果本地缓存中存在资源,则请求将由缓存处理程序作为服务器,并且响应将具有HTTP 200状态,而不是向服务器发送请求。

例如,对于此stackoverflow页面,当我刷新页面时,例如,在 jQuery 的网络标签中也会看到类似的内容。

enter image description here

,但是没有任何获取资源的请求。看着提琴手,有一个请求建立HTTPS连接,但是没有获取jQuery的请求。

enter image description here

2。浏览器何时会发送条件请求?

当缓存过期时,用户代理将发送条件获取请求以验证其内容是否被修改,如果资源未被修改,则服务器将发送HTTP 304响应,并且将与该内容共享新的到期日期。

enter image description here

对于我们的jQuery示例,您可以发送来自邮递员的以下请求:

GET https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js
Header:
Cache-Control: public
If-Modified-Since: Tue,03 Mar 2020 19:15:00 GMT

,您将收到以下响应以及更新的到期日期:

HTTP 304
Date: Fri,16 Oct 2020 08:58:03 GMT
Expires: Sat,16 Oct 2021 08:58:03 GMT
Age: 32066

无需赘述,缓存可以总结为:

1. User agent sends request to server
2. Server responds resource along with "Last-Modified" date
3. Next time same resource is requested,browser will use "Last-Modified" date (aka validator) to check if resource is stale or not
    3.1 If resource is not stale,it will be served from cache
    3.2 If resource is stale,browser will use "Last-Modified" date in header and **send conditional get** to server
        3.2.1 server can resource and send HTTP 200 is resource is updated
        3.2.2 In case resource is not modified,server will send HTTP 304 along with updated `Expiry` date

3。为什么以前可以使用?

说实话,我不确定它为什么能工作。可能有多种原因:

  1. 您的浏览器缓存可能很旧,并且缓存资源的Last-Modified标头具有旧值,原因是从您的用户代理发送了条件获取请求,并且服务器在缓存资源上返回了更新的Last-Modified日期(Expires响应标头)。
  2. 可能是浏览器禁用了缓存(隐身模式或显式使用无缓存)
  3. 服务器可能不支持更早的缓存并且没有发送Last-Modified作为响应 等等。

参考:

  1. https://web.dev/http-cache/
  2. https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
  3. https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9
,

您所描述的只是Chrome开发者工具如何显示来自缓存的响应。还有其他StackOverflow问题(例如this one)可以证实这一点。

状态代码显示为200,因为它就是这样。响应被缓存,响应的一部分是状态码。缓存的响应没有特殊的状态代码。

您误解了304的用途。用来回复conditional request。它代表通过网络接收到的带有该状态码的实际响应,而不是缓存的响应。

要确认响应确实是从缓存中得到的,并且没有新的请求发送到服务器,您可以查看服务器日志。

,

检索到URL后,Web服务器将返回资源的当前表示形式及其相应的ETag值,该值位于HTTP响应标头“ ETag”字段中。

然后,客户端可以决定将表示形式及其ETag一起缓存。

稍后,如果客户端要再次检索相同的URL资源,它将首先确定URL的本地缓存版本是否已过期(通过Cache-Control和Expire标头)。如果URL尚未过期,它将检索本地缓存的资源。如果确定URL已过期(过时),则客户端将与服务器联系,并在“ If-None-Match”字段中发送其先前保存的ETag副本以及请求。 (来源:https://en.wikipedia.org/wiki/HTTP_ETag

但是,即使将来设置了资产的expire时间,浏览器仍然可以按照Vary标头使用ETag到达服务器以进行条件GET。

“ vary”标头的详细信息:https://www.fastly.com/blog/best-practices-using-vary-header/

所以现在缓存中有一个对象,上面有一个小标志,上面写着“仅用于请求中没有接受编码的请求。”

,

尝试删除标签immutable并使用:

Cache-Control: public,max-age=31536000;

您可以在Mozilla's Cache-Control documentation上了解更多信息。

,

这可能无法回答问题,但可以对其他人有所帮助。

我遇到了同样的问题,Chrome 没有正确缓存我的许多资产。在所有其他浏览器上都可以正常工作,但在 Chrome 上不行。我意识到差异之一是我在 Firefox 上得到的 304 响应,而不是在 Chrome 上。此外,内存缓存和磁盘缓存会返回一些文件,但有时不会。

我尝试修改 Cache-Control 标头和 ETag,但仍然没有解决方案。

然后我意识到它在具有有效证书的 QA 和生产环境中运行良好。但是在开发(本地主机)上,事实并非如此。所以我找到了这个 Chrome 配置:

chrome://flags/#allow-insecure-localhost

启用它只是由问题修复。希望它可以帮助其他人。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...