【问题标题】:if-modified-since vs if-none-matchif-modified-since vs if-none-match
【发布时间】:2023-03-31 03:40:02
【问题描述】:

if-modified-since 和 if-none-match 之间有什么区别?我有一种感觉,if-none-match 用于文件,而 if-modified-since 用于页面?

【问题讨论】:

    标签: http caching request response


    【解决方案1】:

    关于Last-Modified/If-Modified-Since和ETag/If-None-Match的区别:

    两者可以互换使用。然而,根据资源的类型,以及它是如何在服务器上生成的,一个或另一个问题(“自从......以来这是否被修改过?”/“这仍然与这个 ETag 匹配吗?”)可能更容易回答.

    例子:

    • 如果您要提供文件,使用文件的mtime 作为Last-Modified 日期是最简单的解决方案。
    • 如果您正在提供由多个 SQL 查询构建的动态网页,则检查这些查询中的任何一个返回的数据是否已更改可能是不切实际的(除非它们都有某种“最后修改”列) .在这种情况下,使用例如将页面内容的 md5 哈希作为ETag 会容易得多。
      OTOH,这意味着您仍然必须在服务器上生成整个页面,即使是有条件的 GET。弄清楚 ETag 中的确切内容(主键、修订号等)可以为您节省大量时间。

    有关该主题的更多详细信息,请参阅以下链接:

    【讨论】:

    • 我已向浏览器发送了一个 ETag,但它从不使用 If-None-Match 请求同一页面。可能是什么问题?
    • @pacerier:浏览器不需要使用 Etag。所以它可能是一个旧的浏览器,只是忽略它。另一种可能性是实体正在使用随着调用而变化的 url 参数进行访问。如果实体名称发生变化,则 etag 不会用于不同的请求。
    • @RafaelBaptista 要详细说明您评论的后半部分,假设我有这种情况:我有一个文件服务器,服务器支持使用 ETags 进行版本控制,出于向后兼容性的原因,我们曾经有客户端使用查询参数 my_current_version=(version)。如果我发送的 HTTP 请求具有不同的 my_current_version 值以及 ETags,那么作为最佳实践,在确定是提供新版本还是发回 304 时,将优先考虑什么标准?谢谢!
    • 服务器如何使用 Etag 取决于服务器。如果您想通过重写规则,您可能可以将大多数文件服务器配置为使用 etag 忽略参数。您对客户端(浏览器)的控制较少。大多数人不会在请求另一组参数时发送他们为一组参数获得的 etag 标头。客户端对 image?v=1 的请求不会为 image?v=2 发送相同的 etag。如果我正在编写自己的服务器,我会将 etag 实现为图像内容的哈希。任何请求资源的 url,并带有一个与我要发送的图像的哈希匹配的 etag,我返回 304。
    【解决方案2】:

    If-Modified-Since 与Last-Modified 进行比较,而If-None-Match 与ETag 进行比较。 Modified-Since 和 ETag 都可用于识别资源的特定变体。

    但是If-Modified-Since 与Last-Modified 的比较可以为您提供缓存变体是旧 还是新 的信息,而If-None-Match 与@987654335 的比较@ 只是为您提供两者是否相同的信息。此外,大多数ETag 生成器是否包含系统特定inode 的信息,因此将文件移动到不同的驱动器也可能会更改ETag。

    【讨论】:

    • 很有趣,但为什么我要使用“相同”检查而不是“上次修改”检查?有什么好处?如果有要提供的文件,哪个是更好的选择?
    • 有了电脑,时间很脆弱。闰秒、夏令时之间的切换和不准确的时钟都可能导致“上次修改”检查返回错误的结果。比较内容本身(或内容的 MD5 哈希)可以避免这些问题。
    • 尽管我完全理解@devdanke,但我想说检查时间戳比检查 md5sum 快得多。这些标头的目的是使其快速,有时最好不要将新版本的实体传输到客户端,而不是使用 I/O 加载服务器。无论如何,用户总是可以按 ctrl+shift+R(或 ctrl+F5 或其他)
    • 对于文件和目录,时间并不是那么脆弱。最后修改时间来自 stat 系统调用的 mtime 字段,它直接来自文件系统,它存储为自纪元以来的秒数。修改文件时会更新 mtime 值。 mtime 是相对于时代而言的,它不会因本地时钟的变化而改变。夏令时等。请注意,浏览器的本地时间或时间变化在这里并不重要 - 浏览器只存储发送到服务器的值,然后在以后的请求中重新发送。
    【解决方案3】:

    Last-Modified/If-Modified-Since 中使用的时间戳值具有有限的精度 - 1 秒,这对于快速变化的内容来说是不够的,例如,网络聊天应用程序可以在其中发布多条消息任何给定的秒数。 ETag/If-None-Match 可以帮助解决这个问题。

    【讨论】:

      【解决方案4】:

      正如谷歌最佳实践中所述:

      为所有可缓存资源指定 Expires 或 Cache-Control max-age 之一以及 Last-Modified 或 ETag 之一非常重要。同时指定 Expires 和 Cache-Control: max-age 或同时指定 Last-Modified 和 ETag 是多余的。

      https://developers.google.com/speed/docs/best-practices/caching

      【讨论】:

      • 该 URL 不再包含类似的文本。没有提到使用Last-Modified 和ETag(或者,在用户代理端,If-Modified-Since 和If-None-Match)没有任何限制。同样,W3 规范不会限制您。它说不要将If-Modified-Since 与If-Match 一起使用,但我认为这是因为具有更新日期但与ETag 定义的内容相同的文档集应该很小。
      【解决方案5】:

      If-Modified-Since 使用日期,而If-None-Match 使用ETag。它们都可以用于“页面”(即 HTML)和其他文件。

      【讨论】:

        【解决方案6】:

        除非服务器声明为弱,否则 ETag 被视为强验证器,因此可用于满足条件范围请求。然而,大多数自动生成的 ETag 在服务器场情况下会出现困难,因为它们经常使用 inode 信息和/或唯一的持久计数器。在实践中,我发现 Last Modified 标头足以容纳相当静态的内容,例如提供受保护的静态内容,因为文件的写入时间是一个相当好的验证器。

        ETag 是迄今为止最灵活的。符合要求的客户端需要在有条件的请求中发送 ETag,而如果可用,他们应该同时发送。

        【讨论】:

          【解决方案7】:

          If-Modified-Since 标头用于指定浏览器上次接收请求资源的时间。 If-None-Match 标头用于指定服务器在上次收到请求的资源时发布的实体标签。

          在所描述的两种方式中,这些标头用于支持浏览器内的内容缓存,它们使服务器能够指示浏览器使用资源的缓存副本,而不是响应资源的全部内容如果这不是必需的。

          【讨论】:

            猜你喜欢
            • 2012-11-27
            • 2018-09-10
            • 1970-01-01
            • 2011-01-07
            • 2011-01-06
            • 1970-01-01
            • 1970-01-01
            • 2014-10-08
            • 1970-01-01
            相关资源
            最近更新 更多