Http 为什么Firefox会忽略缓存头并在刷新时重新验证?

Http 为什么Firefox会忽略缓存头并在刷新时重新验证?,http,firefox,caching,browser,http-headers,Http,Firefox,Caching,Browser,Http Headers,我有一些不可变的图像资源,可以永久缓存。Chrome似乎尊重我的响应标题,并且不会重新验证资源: 下面是Chrome中这些资源之一的示例。如您所见,我包括缓存控制:public、max age、expires、etag和last modified,并且资源由内存缓存提供: 然而,Firefox并不尊重这些头文件,在每次加载时都会重新验证资源!每次页面加载时,我的服务器都会收到每个配置文件pic的请求,并返回304: 以下是一个示例,该示例根据该请求生成304: 我不明白为什么Firefox会忽略

我有一些不可变的图像资源,可以永久缓存。Chrome似乎尊重我的响应标题,并且不会重新验证资源:

下面是Chrome中这些资源之一的示例。如您所见,我包括缓存控制:public、max age、expires、etag和last modified,并且资源由内存缓存提供:

然而,Firefox并不尊重这些头文件,在每次加载时都会重新验证资源!每次页面加载时,我的服务器都会收到每个配置文件pic的请求,并返回304:

以下是一个示例,该示例根据该请求生成304:

我不明白为什么Firefox会忽略缓存头并继续访问服务器以获取缓存。我已经尝试过各种与缓存相关的头文件,并阅读了关于什么是缓存的标准。我已经确保在devtools中启用了缓存。我也尝试过关闭devtools,我一直在服务器日志中看到304s


我发现这只发生在页面刷新时。不过,普通刷新不是shift或shift命令,而是普通刷新。这不是我所期望的行为。

更详细地说,让我详细说明ETag。从技术上讲,Firefox正在正确处理它。当Etag存在时,客户端或中间缓存需要执行GET或HEAD,以确保所提供的内容没有更改

If None Match头告诉服务器它有一个或多个版本。如果未更改,服务器/代理将返回304

您可以通过使其成为弱ETag来修改重新验证行为。这是通过在ETags值前面包含W/来实现的,即ETag:/W。这可以在您的服务器上处理,或者如果您无法通过在CDN上重写规则来控制它

Firefox可能的解决方法是添加缓存控件不可变选项。如果不看Firefox缓存启发法中的代码,我不能肯定,但它应该很容易测试

如果其他服务器不支持标头,则会忽略该标头


ETag也不能处理字节范围请求。所以,如果你没有使用它们的特殊理由,请考虑关闭它们。

只是为了更冗长,让我详述ETAGS。从技术上讲,Firefox正在正确处理它。当Etag存在时,客户端或中间缓存需要执行GET或HEAD,以确保所提供的内容没有更改

If None Match头告诉服务器它有一个或多个版本。如果未更改,服务器/代理将返回304

您可以通过使其成为弱ETag来修改重新验证行为。这是通过在ETags值前面包含W/来实现的,即ETag:/W。这可以在您的服务器上处理,或者如果您无法通过在CDN上重写规则来控制它

Firefox可能的解决方法是添加缓存控件不可变选项。如果不看Firefox缓存启发法中的代码,我不能肯定,但它应该很容易测试

如果其他服务器不支持标头,则会忽略该标头


ETag也不能处理字节范围请求。因此,如果你没有使用它们的特殊原因,就考虑关闭它们。

简单地说:Firefox在浏览器刷新中重新验证缓存内容。 这曾经是所有浏览器所做的。有一段时间,假设用户主动刷新页面是因为出现了问题,他们需要从头开始,这可能是合理的。现在,随着显示实时内容的网站的出现,刷新的使用可能会有很大的不同

Chrome和Firefox似乎采取了不同的方式来处理这个问题。Chrome的方法是使其刷新行为更智能、更复杂,而Firefox则选择依赖开发人员明确指出,不过时的资源永远不需要使用响应头进行重新验证。有关此区别的更多信息,请参见


如果此刷新行为是应用程序的一个重要用例,而不仅仅是用于调试目的,那么添加缓存控制:immutable应该可以解决Firefox中的此问题。

简单地说:Firefox在浏览器刷新时重新验证缓存内容

这曾经是所有浏览器所做的。有一段时间,假设用户主动刷新页面是因为出现了问题,他们需要从头开始,这可能是合理的。现在,随着显示实时内容的网站的出现,刷新的使用可能会有很大的不同

Chrome和Firefox似乎采取了不同的方式来处理这个问题。Chrome的方法是使其刷新行为更智能、更复杂,而Firefox则选择依赖开发人员明确指出,不过时的资源永远不需要使用响应头进行重新验证。有关此区别的更多信息,请参见

如果这是真的
对于您的应用程序来说,h行为是一个重要的用例,而不仅仅是用于调试的东西。添加缓存控制:immutable应该可以解决Firefox中的这个问题。

@KevinChristopherHenry感谢您的提问。我想在我的问题中提到这一点:我确实检查了好几次,但我没有启用它。我一直希望这就是问题所在……我也尝试过关闭devtools,但我确实一直在服务器日志中看到304s。是的,最大年龄=0我不明白。我已经通过refresh命令/control+r访问了该页面,但我将尝试使用页面导航。这很有趣。>关于这一点,这里有很多答案。我会搜索的,谢谢。嘿,我可以确认导航模式确实会影响行为。使用浏览器后退/前进或基于应用程序的路由,Firefox不会发出请求!是刷新导致了这种行为。不过,普通刷新不是shift或shift命令,而是普通刷新。这不是我所期望的行为。@KevinChristopherHenry如果你想公布答案,我会投赞成票/接受票。谢谢你的帮助。@Kevinchristherhenry谢谢你的邀请。我想在我的问题中提到这一点:我确实检查了好几次,但我没有启用它。我一直希望这就是问题所在……我也尝试过关闭devtools,但我确实一直在服务器日志中看到304s。是的,最大年龄=0我不明白。我已经通过refresh命令/control+r访问了该页面,但我将尝试使用页面导航。这很有趣。>关于这一点,这里有很多答案。我会搜索的,谢谢。嘿,我可以确认导航模式确实会影响行为。使用浏览器后退/前进或基于应用程序的路由,Firefox不会发出请求!是刷新导致了这种行为。不过,普通刷新不是shift或shift命令,而是普通刷新。这不是我所期望的行为。@KevinChristopherHenry如果你想公布答案,我会投赞成票/接受票。谢谢你的帮助。嘿,我试试看,谢谢。如果没有任何匹配超出我的控制。。。它包括在内,因为我包括一个Etag。我不记得我是否试过不包括Etag。我会再试一次。我正在研究immutable,但我不确定是否可以将它与public、max age一起指定,以及它将如何与其他不支持它的浏览器交互。我也留下了这样的评论:你需要Etag吗?如果是这样,您还可以尝试将其转换为允许使用缓存副本的弱Etag。Etag:W/。。。。。。。。。。。。。。这是关于它们的wiki帖子。不,ETag的存在不会阻止浏览器缓存。它只是提供了一种机制,用于在资源确实过期时重新验证资源。OP看到的行为是因为他们正在刷新页面,而Firefox中的刷新会触发重新验证。如果没有重新验证头,刷新将导致更昂贵的常规请求。他仍然有过期和上次修改,因此结果仍然是服务器的IMS,就像他得到的一样。我的大部分经验来自于构建三个CDN,我真的不能说Firefox是做什么的,但我知道我们会如何处理它。是的,看起来这里讨论了这一点:。最大年龄=0,重新验证是因为我正在刷新。后退/前进和历史API导航不会导致重新验证。有趣的是Chrome怎么不这么做。我测试了添加immutable和删除etag,但这并没有改变行为@KevinChristopherHenryHey我会试试的,谢谢。如果没有任何匹配超出我的控制。。。它包括在内,因为我包括一个Etag。我不记得我是否试过不包括Etag。我会再试一次。我正在研究immutable,但我不确定是否可以将它与public、max age一起指定,以及它将如何与其他不支持它的浏览器交互。我也留下了这样的评论:你需要Etag吗?如果是这样,您还可以尝试将其转换为允许使用缓存副本的弱Etag。Etag:W/。。。。。。。。。。。。。。这是关于它们的wiki帖子。不,ETag的存在不会阻止浏览器缓存。它只是提供了一种机制,用于在资源确实过期时重新验证资源。OP看到的行为是因为他们正在刷新页面,而Firefox中的刷新会触发重新验证。如果没有重新验证头,刷新将导致更昂贵的常规请求。他仍然有过期和上次修改,因此结果仍然是服务器的IMS,就像他得到的一样。我的大部分经验来自于构建三个CDN,我真的不能说Firefox是做什么的,但我知道我们会如何处理它。是的,看起来这里讨论了这一点:。最大年龄=0,重新验证是因为我正在刷新。后退/前进和历史API导航不会导致重新验证。有趣的是Chrome怎么不这么做。我测试了添加immutable和删除etag,但这并没有改变行为@凯文斯
谢谢你的历史背景。注意:我尝试了缓存控制:在Firefox中不可变,对刷新没有影响。也就是说,我尝试将其作为一项指令添加到max age和public旁边。我没有把它作为一个独立的指令来尝试,因为Chrome没有被列为支持它,我也不想尝试使用多个缓存控制头。我可以在刷新时重新验证,只要这是Firefox的预期行为。还没有尝试过,但我认为stale while revalidate在这里也可能有用:。根据我对该页面的粗略浏览,在检索304时,至少会显示陈旧的图像。@DmitryMinkovsky:如果您关心的是页面的响应性而不是服务器上的负载,那么这可能是一个很好的解决方案,因为请求数是相同的。尽管浏览器通常支持它,但在刷新时仍可能不使用它。immutable似乎是更好的解决方案,尽管我不确定为什么它在您的案例中不起作用。也不知道immutable为什么不起作用。我只是再次尝试将其添加到缓存控制指令列表中。没有运气。无论如何,刷新时,FF重新验证。过时,而重新验证似乎也不能加快速度,再加上重新验证。我想这就是FF的工作原理。感谢历史背景。注意:我尝试了缓存控制:在Firefox中不可变,对刷新没有影响。也就是说,我尝试将其作为一项指令添加到max age和public旁边。我没有把它作为一个独立的指令来尝试,因为Chrome没有被列为支持它,我也不想尝试使用多个缓存控制头。我可以在刷新时重新验证,只要这是Firefox的预期行为。还没有尝试过,但我认为stale while revalidate在这里也可能有用:。根据我对该页面的粗略浏览,在检索304时,至少会显示陈旧的图像。@DmitryMinkovsky:如果您关心的是页面的响应性而不是服务器上的负载,那么这可能是一个很好的解决方案,因为请求数是相同的。尽管浏览器通常支持它,但在刷新时仍可能不使用它。immutable似乎是更好的解决方案,尽管我不确定为什么它在您的案例中不起作用。也不知道immutable为什么不起作用。我只是再次尝试将其添加到缓存控制指令列表中。没有运气。无论如何,刷新时,FF重新验证。过时,而重新验证似乎也不能加快速度,再加上重新验证。我想这就是FF的工作原理。