互联网工程任务组 (IETF) P. McManus
请求评议:8246 Mozilla
类别:标准轨道 2017年9月
ISSN: 2070-1721

HTTP 不可变响应


摘要

不可变 HTTP 响应 Cache-Control 扩展允许服务器标识在新鲜期内不会被更新的资源。这保证了客户端无需重新验证已缓存的新鲜资源即可确定其未被修改。

本备忘录的状态

这是一个互联网标准轨道文档。

本文件是互联网工程任务组 (IETF) 的成果,代表 IETF 社区的共识。它已获得公开评审,并由互联网工程指导小组 (IESG) 批准发布。关于互联网标准的更多信息请参见 RFC 7841 第2节

关于本文档的当前状态、勘误及如何反馈信息,可访问 https://www.rfc-editor.org/info/rfc8246 获取。

Copyright Notice

Copyright (c) 2017 IETF Trust and the persons identified as the document authors. All rights reserved.

This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (https://trustee.ietf.org/license-info) in effect on the date of publication of this document. Please review these documents carefully, as they describe your rights and restrictions with respect to this document. Code Components extracted from this document must include Simplified BSD License text as described in Section 4.e of the Trust Legal Provisions and are provided without warranty as described in the Simplified BSD License.


1. 引言

HTTP 的新鲜期机制 [RFC7234] 允许客户端在指定的时间段内安全地复用已存储的响应以满足后续请求。然而,在该时间段内资源仍然有可能被修改。

例如,首页报纸的照片新鲜期为一小时,意味着没有用户会看到缓存超过一小时的照片。但照片可以随时被更新,导致不同用户在长达一小时内看到的照片因各自缓存内容不同而不同。这符合 [RFC7234] 定义的缓存机制。

需要确认缓存响应未被更新的用户通常会使用其用户代理的重新加载(或刷新)机制。这会生成条件请求 [RFC7232],并返回新的内容或(如果未修改)返回 304(未修改)响应 [RFC7232]。理解 HTML 并获取其依赖子资源的用户代理,可能会为刷新整个页面的所有部分发出数百个条件请求 [REQPERPAGE]

然而,有些内容提供者只会为子资源创建一个版本,因为他们使用“版本化”URL。当这些资源需要更新时,只需以新 URL 发布,通常会在路径中嵌入该版本唯一的标识符,并将所有引用此子资源的链接替换为新路径。

例如,https://www.example.com/101016/main.css 可能会被更新并以 https://www.example.com/102026/main.css 重新发布,所有引用它的链接也会同步更改。该设计模式允许子资源拥有极长的新鲜期,无需预测将来何时会被更新。

但用户代理无法得知该版本化 URL 设计模式是否被采用。因此,用户主动刷新依然会导致每个子资源都发起不必要的条件请求,而每个请求只会返回 304 响应。

immutable HTTP 响应 Cache-Control 扩展允许服务器标识在其新鲜期内不会被更新的响应。

这样可以有效地告知客户端,对于该响应,任何条件请求都可以安全地跳过,无需担心其已被更新。

1.1. 符号约定

本文件中的关键词 “MUST”(必须)、“MUST NOT”(禁止)、“REQUIRED”(需要)、“SHALL”(应)、“SHALL NOT”(不应)、“SHOULD”(建议)、“SHOULD NOT”(不建议)、“RECOMMENDED”(推荐)、“NOT RECOMMENDED”(不推荐)、“MAY”(可以)以及 “OPTIONAL”(可选),应按照 BCP 14 [RFC2119][RFC8174] 的说明进行解释,仅当这些词全部大写时适用,如本处所示。


2. 不可变 Cache-Control 扩展

当该扩展出现在 HTTP 响应中时,表示源服务器在响应的新鲜期内不会更新该资源的表现形式。

客户端在响应的新鲜期内(例如刷新时)不应发起条件请求,除非用户明确要求(如强制刷新)。

immutable 扩展仅适用于已存储响应的新鲜期内。过期的响应应像没有 immutable 扩展时一样进行重新验证。

immutable 扩展没有参数。如果出现任何参数,则无意义且必须被忽略。多次出现 immutable 扩展等同于出现一次。在请求中出现 immutable Cache-Control 扩展无效。

2.1. 关于中间人

当代理客户端收到不可变响应时,其语义与用户代理客户端收到时相同。因此,代理应跳过对包含 immutable 扩展的新鲜响应的条件性重新验证,除非客户端有信号表明需要验证(如 RFC7234 第5.2.1.4节 中定义的 no-cache Cache-Control 请求指令)。

代理使用 immutable 扩展绕过条件性重新验证时,可根据收到的请求头选择回复 304 或 200 给其请求客户端。

2.2. 示例

Cache-Control: max-age=31536000, immutable

3. 安全性注意事项

immutable 机制是一种软性绑定机制,与所有绑定机制一样,为缓存污染事件的放大提供了攻击向量,包括缓存投毒攻击。为缓解这一风险,建议采用三种机制:

  • 客户端应忽略非认证上下文(如非 HTTPS)的资源中的 immutable 扩展。认证资源对缓存投毒攻击的抵抗力较强。
  • 用户代理通常提供两种刷新机制:普通刷新和某种形式的强制刷新。后者用于修复中断加载等问题。这些刷新(通常通过 no-cache 请求属性指示)也应忽略 immutable 扩展。
  • 对于无法强烈指示已存储响应大小等于实际响应大小的资源(如通过连接关闭分界的响应),客户端应忽略 immutable 扩展。

4. IANA 注意事项

immutable 扩展已根据 RFC7234 第7.1节 的指引,注册到“超文本传输协议(HTTP)缓存指令注册表”中。

  • 缓存指令:immutable
  • 参考文献:RFC 8246

5. 参考文献

5.1. 规范性引用

[RFC2119]
Bradner, S., “用于 RFC 中指示需求级别的关键词”, BCP 14, RFC 2119, DOI 10.17487/RFC2119, 1997年3月, <https://www.rfc-editor.org/info/rfc2119>.
[RFC7232]
Fielding, R., Ed. 和 J. Reschke, Ed., “超文本传输协议 (HTTP/1.1):条件请求”, RFC 7232, DOI 10.17487/RFC7232, 2014年6月, <https://www.rfc-editor.org/info/rfc7232>.
[RFC7234]
Fielding, R., Ed., Nottingham, M., Ed., 和 J. Reschke, Ed., “超文本传输协议 (HTTP/1.1):缓存”, RFC 7234, DOI 10.17487/RFC7234, 2014年6月, <https://www.rfc-editor.org/info/rfc7234>.
[RFC8174]
Leiba, B., “RFC 2119 关键词大小写歧义”, BCP 14, RFC 8174, DOI 10.17487/RFC8174, 2017年5月, <https://www.rfc-editor.org/info/rfc8174>.

致谢

感谢 Ben Maurer 在本想法的开发与测试上的合作。感谢 Amos Jeffries 协助代理交互,感谢 Mark Nottingham 帮助完善文档。


作者地址

Patrick McManus
Mozilla
电子邮箱: mcmanus@ducksong.com