如何防止返回304的请求

时间:2014-10-02 17:43:17

标签: http caching http-headers etag

浏览器何时不向服务器请求文件?

换句话说,我有一个JavaScript文件。其HTTP响应标头包含ETagCache-Control: publicExpires: Tue, 19 Jan 2038 03:14:07 GMT

服务器在浏览器缓存已准备就绪后返回304

我的问题是,为什么浏览器甚至会检查服务器并首先获得304?我不希望浏览器询问是否有新版本 - 它应该直接从浏览器缓存加载而不检查服务该脚本的服务器的修改。

HTTP响应标头的哪些组合可以实现此目的?

4 个答案:

答案 0 :(得分:87)

首先,相关的HTTP规范是RFC 7234。如果你看一下规范,你会发现两件事:

  • 规范从不要求,在任何情况下,缓存都会提供内容的缓存版本,而无需重新验证。有很多地方规范指出缓存不得使用缓存内容来满足请求,但根本没有任何地方它指示它必须这样做或者它必须不重新验证。因此,浏览器供应商可以随时自由重新验证。
  • 其次,你最终没有做错任何事。浏览器可以自由缓存响应,并根据您返回的标头使用这些缓存的响应。关键点在Section 4,其中注意到提供缓存响应的条件之一是响应是:

      
        
    • 新鲜(参见第4.2节)或

    •   
    • 允许陈旧(见第4.2.4节)或

    •   
    • 成功验证(参见第4.3节)。

    •   

    由于您正在吐出一个将来很远的Expires标题,并且未来尚未达到该点,因此响应为“新鲜”,因此不需要重新验证。所以你正在做的事情,规范建议你应该在你的最后。 (尽管使用Cache-Control: max-age=foo是一种比使用Expires:标头更加现代的设置缓存到期时间的方法。)

因此,如果你想改变浏览器的缓存行为,那你就不走运了。

然而,事情可能没有您想象的那么糟糕。您可能只是看到了请求和304,因为您在测试时刷新浏览器中的页面。浏览器根据触发请求的方式不同地处理缓存的资源。

我运行了一个简单的测试,其中我创建了一个HTML页面,其中包含指向JS文件的<script>标记,指向图像的<img>标记以及<link>标记指向CSS样式表。所有这些文件都托管在配置为使用以下服务的Apache服务器上:

  • 一个E-Tag标题,
  • 最后修改日期
  • Cache-Control: max-age=172800标题

当然,所有资源都在首页加载时提供了200个代码。此后,使用默认设置在Chrome或Firefox中进行测试,我观察到:

  • 如果您通过 F5 键或刷新按钮刷新页面,页面和所有资源都会重新生效(即发出请求)到每个资源的服务器和304返回)。
  • 如果您通过链接返回页面或在新标签页的URL栏中输入网址,则重新验证已完成(即没有请求)。
  • 在Chrome中,如果您通过选择网址栏并按Enter来刷新页面,则页面本身会重新生效,但没有其他资源可以。在Firefox中,页面和资源都没有重新验证。

This page表示Internet Explorer具有相同的行为:

  

在许多情况下,Internet Explorer需要检查缓存条目是否有效:

     
      
  • 缓存条目没有到期日期,并且首次在浏览器会话中访问内容
  •   
  • 缓存条目的截止日期已过期
  •   
  • 用户通过单击“刷新”按钮或按F5
  • 请求页面更新   

换句话说,如果用户明确刷新页面,通常只会看到这些重新验证请求。除非您对浏览器缓存的行为方式有一些非常特殊的要求,否则这种行为似乎非常合理。

GoogleMozilla都有一些关于HTTP缓存的文档(我在MSDN或Apple Developers网站上找不到任何相同内容),但都没有建议存在任何特定于供应商的缓存头可用于修改浏览器用于选择何时重新验证的规则。你想做的事情根本不可能。

如果您确实需要对此行为进行更多控制,可以使用HTML5本地存储查看HTML5 Application Cache或滚动自己的缓存逻辑,例如basket.js

答案 1 :(得分:0)

Expires:Cache-Control: max-age=应该有效。您是否在服务器日志中确认浏览器实际上正在进行网络呼叫?例如,我发现萤火虫的输出结果令人困惑,这表明当你实际进入缓存时,你正在进行远程调用。

答案 2 :(得分:0)

如果您在我的船上并将一个Angular应用程序部署到IIS,请确保您的web.config配置为正确地重写该URL,如下所示:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <system.webServer>
        <httpErrors errorMode="Detailed" />
        <rewrite>
            <rules>
                <rule name="Angular Routes" stopProcessing="true">
                    <match url=".*" />
                    <conditions logicalGrouping="MatchAll">
                        <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
                        <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
                    </conditions>
                    <action type="Rewrite" url="/NameOfYourApp_UnderDefaultWebSite/" />
                </rule>
            </rules>
        </rewrite>
  </system.webServer>
</configuration>
  

特别注意<action type="Rewrite" url="/NameOfYourApp_UnderDefaultWebSite/" />

中网址的值

答案 3 :(得分:-2)

以后设置Expires标头超过一年的规则违反 HTTP 1.1 RFC

因此,此处的HTTP响应标头无效(Expires: Tue, 19 Jan 2038 03:14:07 GMT)。解决这个问题可能会解决问题!