Skip to content

HTTP Caching ​

1. Introduction ​

HTTP(超文本传输协议)是一种无状态的应用层协议,常用于分布式信息系统。它通过请求/响应机制实现网络上的超文本信息交互。HTTP 缓存用于存储响应消息,以减少响应时间和网络带宽消耗。缓存可以是共享缓存(供多个用户使用)或私有缓存(仅供单个用户使用)。

2. Overview of Cache Operation ​

HTTP 缓存的主要目标是通过重用先前的响应消息来提高性能。缓存会将存储的响应视为“新鲜的”,如果可以在不验证的情况下重用它。否则,缓存需要验证响应是否仍然有效。

3. Storing Responses in Caches ​

缓存存储响应的条件包括请求方法被缓存理解、响应状态码是最终的、响应不包含 no-store 指令等。缓存必须包括所有接收到的响应头字段,并在某些情况下更新存储的响应头字段。

3.1. Storing Header and Trailer Fields ​

缓存必须包含所有接收到的响应头字段,但某些字段如 Connection 字段和特定代理使用的字段除外。

3.2. Updating Stored Header Fields ​

缓存需要在某些情况下更新存储的响应头字段,例如在接收到新的部分内容或验证响应时。

3.3. Storing Incomplete Responses ​

缓存可以存储不完整的响应,但必须记录其不完整状态,并且不得使用不完整的响应来回答请求,除非该请求是部分的并且指定的范围完全在不完整响应内。

3.4. Combining Partial Content ​

缓存可以将多个部分内容组合成单个存储的响应,但必须更新存储的响应头字段。

3.5. Storing Responses to Authenticated Requests ​

共享缓存不得使用带有 Authorization 头字段的请求的缓存响应,除非响应包含允许共享缓存存储的指令。

4. Constructing Responses from Caches ​

缓存在使用存储的响应满足请求时,必须确保请求的 URI 与存储的响应匹配,请求方法允许使用存储的响应,并且存储的响应是新鲜的、允许过期或已成功验证的。

4.1. Calculating Cache Keys with the Vary Header Field ​

当缓存接收到一个可以由存储的响应满足的请求时,如果该存储的响应包含 Vary 头字段,缓存必须确保所有列出的请求头字段匹配。

4.2. Freshness ​

响应的新鲜度由其生成时间与过期时间之间的时间长度决定。缓存可以使用显式或启发式方法来确定响应的过期时间。

4.3. Validation ​

当缓存无法使用存储的响应满足请求时,可以使用条件请求机制进行验证,以更新存储的元数据或替换存储的响应。

4.4. Invalidating Stored Responses ​

由于不安全的请求方法可能会改变服务器上的状态,中间缓存需要使存储的响应无效,以保持内容的最新。

5. Field Definitions ​

5.1. Age ​

Age 响应头字段表示响应生成或成功验证的时间估计值。

5.2. Cache-Control ​

Cache-Control 头字段用于列出沿请求/响应链的缓存指令。

5.2.1. Request Directives ​

  • max-age : 客户端希望响应的年龄不超过指定的秒数。
  • max-stale : 客户端愿意接受超过新鲜度生命周期的响应。
  • min-fresh : 客户端希望响应在指定时间内仍然是新鲜的。
  • no-cache : 客户端希望在没有成功验证的情况下不使用存储的响应。
  • no-store : 缓存不得存储请求或响应的任何部分。
  • no-transform : 客户端请求中间人不对内容进行转换。
  • only-if-cached : 客户端只希望获得存储的响应。

5.2.2. Response Directives ​

  • max-age : 响应在其年龄超过指定秒数后被视为陈旧。
  • must-revalidate : 一旦响应变得陈旧,缓存必须成功验证后才能重用。
  • must-understand : 限制响应的缓存到理解并符合该响应状态码要求的缓存。
  • no-cache : 响应必须在没有成功验证的情况下不被使用。
  • no-store : 缓存不得存储请求或响应的任何部分。
  • no-transform : 中间人不得转换内容。
  • private : 共享缓存不得存储响应。
  • proxy-revalidate : 共享缓存必须在成功验证后才能重用陈旧的响应。
  • public : 缓存可以存储响应,即使通常禁止。
  • s-maxage : 共享缓存的最大年龄。

5.3. Expires ​

Expires 响应头字段表示响应被视为陈旧的日期/时间。

5.4. Pragma ​

Pragma 请求头字段用于 HTTP/1.0 缓存,指定 no-cache 请求。

5.5. Warning ​

Warning 头字段用于传递关于消息状态或转换的附加信息。

6. Relationship to Applications and Other Caches ​

应用程序使用 HTTP 时,可能会指定额外的缓存形式,例如浏览器的历史机制。HTTP 缓存要求不一定适用于应用程序如何使用从 HTTP 缓存中检索到的数据。

7. Security Considerations ​

7.1. Cache Poisoning ​

缓存中存储恶意内容可能会影响多个用户。缓存中毒攻击利用实现漏洞、提升权限或其他技术将响应插入缓存。

7.2. Timing Attacks ​

缓存的使用可能泄露关于哪些资源已被请求的信息。例如,攻击者可以通过加载已知存在于第一个站点上的响应来推测用户是否访问过该站点。

7.3. Caching of Sensitive Information ​

实现和部署中的缺陷可能导致缓存敏感信息,暴露给未经授权的方。

8. IANA Considerations ​

IANA 更新了 HTTP 字段名称注册表和 HTTP 缓存指令注册表。

ABNF ​

abnf
Age = delta-seconds
Cache-Control = [ cache-directive *( OWS "," OWS cache-directive ) ]
Expires = HTTP-date
HTTP-date = <HTTP-date, see [HTTP], Section 5.6.7>
OWS = <OWS, see [HTTP], Section 5.6.3>
cache-directive = token [ "=" ( token / quoted-string ) ]
delta-seconds = 1*DIGIT
field-name = <field-name, see [HTTP], Section 5.1>
quoted-string = <quoted-string, see [HTTP], Section 5.6.4>
token = <token, see [HTTP], Section 5.6.2>