Chrome会忽略ETag标头,只使用内存缓存/磁盘缓存

时间:2017-04-27 13:47:05

标签: google-chrome http nginx server

如果我理解正确,使用ETag的流程就像现在描述的那样:

  • 浏览器将请求发送到服务器。服务器使用ETag
  • 发回图像
  • 浏览器将资源与ETag一起保存
  • 在下一个请求中,浏览器发送包含已保存ETag的标题If-None-Match的请求。

当返回回复时,chrome dev工具告诉我这些是我的标题

Cache-Control:max-age=7200
Connection:keep-alive
Content-Type:image/png
Date:Thu, 27 Apr 2017 13:42:57 GMT
ETag:"b36f59c868d4678033d318a182658e18371df8f5"
Expires:Thu, 27 Apr 2017 15:42:57 GMT
Server:nginx
Transfer-Encoding:chunked
X-Debug-Token:873c8f
X-Debug-Token-Link:http://localhost:8081/_profiler/873c8f

现在,当我重新加载页面时,不会收集新图像。它可以通过Chrome的内存缓存或磁盘缓存保存,如您所见

Chrome dev tab

但为什么会这样呢?我发送了一个ETag,为什么浏览器不向服务器发出另一个请求,而是使用它自己的缓存?

我问的原因是,我们想要缓存我们的图像,但是一旦它们发生变化,它们应该立即更新。为什么Chrome会这样做?

更新
我只是注意到它在Firefox上有用,所以这似乎是一个chrome“功能”而不是配置。

更新2
为此图像设置我的新标题后

Cache-Control:max-age=0, private
Connection:keep-alive
Content-Type:image/png
Date:Thu, 27 Apr 2017 14:44:57 GMT
ETag:"e5b18bdebe44ed4bba3acb6584d9e6a81692ee27"
Expires:Fri, 27 Oct 2017 14:44:57 GMT
Server:nginx
Transfer-Encoding:chunked
X-Debug-Token:3447a6
X-Debug-Token-Link:http://localhost:8081/_profiler/3447a6

Chrome仍然使用磁盘缓存来存储数据。这是我现在的nginx

location ~* \.(?:jpg|jpeg|gif|png|ico|cur|gz|svg|svgz|mp4|ogg|ogv|webm|htc)$ {
  access_log off;
  add_header Cache-Control "max-age: 0, must-revalidate";
}

更新3
我刚做了一些进一步的研究。设置Expires标记后,Chrome会立即使用内存或磁盘缓存。与max-age相同。我不明白,即使设置了must-revalidate,只要设置Expiresmax-age=>0,Chrome就不会重新加载资源。

4 个答案:

答案 0 :(得分:3)

服务器告诉chrome该资源在接下来的2小时(7200秒)内是好的。据推测,你的第二个要求早于此。

max-age: 0, must-revalidate304 Not Modified可以提供更好的服务。然后,虽然你永远不会得到一个完全缓存的操作(甚至没有打扰到服务器),你仍然可以让服务器发送{{1}}响应告诉浏览器它可以使用缓存的实体(并更新任何元数据)基于标题(如果适用)所以当你仍然发生请求响应时,只会发送大约300字节而不是实体的数千字节或更多。

答案 1 :(得分:0)

这是旧文章,但这是我们解决的方法。

@Musterknabe 关于更新3的评论:

即使设定之后,我们也发生了同样的事情 must-revalidate chrome没有重新加载新资源。我发现,由于客户端/浏览器高速缓存中已经存在资源,因此可以从内存高速缓存中获取资源,并且不会触发新请求(获取静态资源)。因此,响应标头未使用must-revalidate

更新

为解决此问题,我们使用了两个步骤:
1.更改的资源文件名-确保将触发新请求
  2.在静态文件中添加了缓存控制标头(在startup.cs中)-用于将来对静态资源文件的更改。这样一来,我们不必更改资源文件名。

    public void Configure(IApplicationBuilder app)
    {
        app.UseStaticFiles(new StaticFileOptions
        {
            OnPrepareResponse = ctx =>
            {
                const int durationInSeconds = 0;
                ctx.Context.Response.Headers[HeaderNames.CacheControl] =
                    "must-revalidate,max-age=" + durationInSeconds;
            }
        });
    }

希望有帮助。

答案 2 :(得分:0)

对于可能登陆这里的任何其他人,请注意 Chrome 不会缓存任何任何 SSL 错误(例如,如果您使用的是自签名的证书)。

让我找到线索的原始帖子:https://stackoverflow.com/a/55101722/9536265

Chrome 错误:https://bugs.chromium.org/p/chromium/issues/detail?id=110649(看起来他们永远不会修复它,这看起来很荒谬,因为几乎所有开发人员都会在这种情况下进行开发)

我无法通过文档进行确认,但 Edge Chromium 的行为似乎相同。另一方面,Firefox 很乐意为使用“不安全”证书的站点(例如站点名称不完全匹配或自签名证书的站点)遵循标准缓存实践。我还没有测试过 Safari。

答案 3 :(得分:0)

要使用 ETag 和浏览器发送 If-Modified-SinceIf-None-Match 标头,缓存控件必须设置为 no-cache

服务器使用 Cache-Control: no-cache header 或浏览器通过 Request.cache = 'no-cache' option


在此处阅读有关缓存选项的更多信息:https://developer.mozilla.org/en-US/docs/Web/API/Request/cache

相关问题