为什么 Chrome 使用 max-age header 请求已缓存的图像?

Why does Chrome make a request for already cached image with max-age header?

我的目标是在浏览器缓存中缓存图像。

当前设置

Cache-Control: public, max-age=10368000 header 附加到请求的图片以缓存图片。

此外,ETag: f5f9f1fb39790a06c5b93735ac6e2397 header 也被附加以检查图像是否在达到 max-age 后发生变化。

当再次请求相同的图像时,检查if-none-match header 的值以查看图像是否已更改。如果没有,304 是 returned.

我正在使用 Fiddler 检查 http 流量(注意 - 下面描述的行为已经在 Fiddler 之前发生,所以这不是问题)

Chrome 版本 - 77.0.3865.90(正式版)(64 位)

预期行为

我预计图像会被缓存 10368000 秒。除非经过 10368000 秒,否则每次请求都会从浏览器的缓存中获取图像。一旦 10368000 秒过去,就会向检查 Etag 的服务器发出请求。如果服务器上的图像没有改变,return 304 到客户端并将缓存时间延长到另一个 10368000 秒。

与Google的行为Chrome

  1. 第一次请求图片。下面是请求 headers

  1. 图片已成功 returned,状态为 200。以下是回复 headers

Fiddler 告知已请求并提供图像

此外,图像被缓存的事实在 ~/Library/Caches/Google/Chrome 中显示。

  1. 单击浏览器中的link栏,然后按回车键再次请求图像。下面是请求 headers

  1. 图像已成功 returned,状态为 304。以下是回复 headers

Fiddler 告诉图像是从缓存中提供的

为什么 Chrome 对图像进行额外的请求并仅在收到 304 响应后才从缓存中提供它?

我看到在第二次请求图像时设置了 Cache-Control: max-age=0 请求 header。据我了解,这意味着 Chrome 想要 re-validate 如果缓存的图像在提供之前有效。但是为什么?

网上有人说 Etag header 是 Chrome 确保图像有效的原因。即使我不包含 Etag header,在第一个响应中只有 Cache-Control: public, max-age=10368000Cache-Control: max-age=0 存在于第二个请求的 headers.

我也试过排除 public,将其设为私有等。我还添加了 ExpiresLast-Modifiedmax-age=10368000 配对并得到相同的行为。

此外,在开发工具中我没有选中禁用缓存。因此肯定会启用缓存,这也很有意义,因为图像是在 returning 304.

之后提供的

当我没有单击 link 栏并按 Enter,而是按刷新箭头,也就是 CMD + R 时,也会发生这种确切的行为。如果我执行硬刷新 CMD + SHIFT + R,则请求图像好像是第一次申请,有道理

Firefox 的行为

Firefox 完全符合预期。

  1. 第一次请求图片。下面是请求 headers

  1. 图片已成功 returned,状态为 200。以下是回复 headers

Fiddler 告知已请求并提供图像

此外,如果我将鼠标悬停在响应状态上,则会显示 OK

  1. 单击浏览器中的link栏,然后按回车键再次请求图像。下面是请求 headers

  1. 图片已成功 returned,状态为 200。以下是回复 headers

但是 Firefox 显示它已被缓存。

此外,Fiddler 在第二次请求时未检测到 activity,因此图像是从 Firefox 的缓存中提供的。不像 Chrome,它向服务器发出另一个请求只是为了从它接收 304。

非常感谢您的宝贵时间和帮助。我非常感谢并愿意提供任何其他信息。真的很期待你对此的看法。

祝你有愉快的一天:)

Why did Chrome make an additional request for the image and served it from the cache only after it received 304 response?

因为你告诉它 - 不管你是否意识到!当您向前和向后浏览时,将使用缓存的图像。当您单击刷新或 F5(MacOS 上的 Cmd R)或页面时,您明确要求 Chrome 仔细检查该页面是否仍然是正确的页面。所以当你点击 URL 栏并点击回车时是一样的。 Chrome 认为你这样做的唯一原因是,你已经在 URL 上,你必须希望它检查。

I see that when requesting the image second time Cache-Control: max-age=0 request header is set. As I understand, it means that Chrome wants to re-validate if cached image is valid before serving it. But why?

正确。 See the answer to this question。至于为什么 - 因为按照上面你有 Chrome 一个你想刷新的信号。

还有 ,它旨在告诉浏览器永远不要重新获取缓存中的内容 - 即使在刷新时也是如此。

Firefox works exactly as expected.

有意思。我实际上喜欢 Chrome 这样做的方式。当然是为了重新加载 (F5/Cmd + R)。感谢它让你感到困惑(虽然希望现在你理解它会减少混淆),但测试这不是常态,大多数人不会点击 URL 栏然后在不更改 [=28= 的情况下按回车键] 除非他们想用服务器重新检查当前页面。