跳到主要内容

5. 字段定义 (Field Definitions)

本节定义与缓存相关的 HTTP 字段的语法和语义.

5.1 Age

"Age" 响应头字段传达发送方对响应自源服务器生成或成功验证以来经过时间的估计. Age 值按第 4.2.3 节的规定计算.

Age = delta-seconds

Age 字段值是非负整数, 表示以秒为单位的时间 (见第 1.2.2 节).

虽然它被定义为单例头字段, 但遇到具有基于列表的 Age 字段值的消息时, 缓存 SHOULD 使用字段值中的第一个成员, 并丢弃后续成员.

如果字段值 (按上文丢弃其他成员后) 无效 (例如包含非非负整数的内容), 缓存 SHOULD 忽略该字段.

Age 头字段的存在意味着该响应不是由源服务器为此请求生成或验证的. 但是, 缺少 Age 头字段并不意味着已经联系过源服务器.

5.2 Cache-Control

"Cache-Control" 头字段用于列出请求/响应链上缓存使用的指令. 缓存指令是单向的: 请求中存在某个指令并不意味着响应中也存在或复制了同一指令.

关于如何处理其他地方定义的 Cache-Control 指令, 见第 5.2.3 节.

无论代理是否实现缓存, 都 MUST 在转发消息中透传缓存指令, 不论这些指令对该应用有何意义, 因为这些指令可能适用于请求/响应链上的所有接收方. 不可能将某个指令定向到特定缓存.

缓存指令由 token 标识 (以大小写不敏感方式比较), 并具有可选参数, 参数可以同时使用 token 和 quoted-string 语法. 对于下面定义且定义了参数的指令, 接收方 SHOULD 接受两种形式, 即使生成时要求使用特定形式.

Cache-Control   = #cache-directive

cache-directive = token [ "=" ( token / quoted-string ) ]

对于下面定义的缓存指令, 除非另有说明, 否则未定义 (也不允许) 参数.

5.2.1 请求指令 (Request Directives)

本节定义缓存请求指令. 它们是建议性的; 缓存 MAY 实现它们, 但并不要求实现.

5.2.1.1 max-age

参数语法:

delta-seconds (see Section 1.2.2)

max-age 请求指令表示客户端偏好年龄小于或等于指定秒数的响应. 除非同时存在 max-stale 请求指令, 否则客户端不希望收到陈旧响应.

此指令使用参数语法的 token 形式: 例如 'max-age=5' 而不是 'max-age="5"'. 发送方 MUST NOT 生成 quoted-string 形式.

5.2.1.2 max-stale

参数语法:

delta-seconds (see Section 1.2.2)

max-stale 请求指令表示客户端愿意接受已经超过其新鲜生命周期的响应. 如果存在值, 客户端愿意接受超过其新鲜生命周期不多于指定秒数的响应. 如果没有为 max-stale 分配值, 客户端将接受任何年龄的陈旧响应.

此指令使用参数语法的 token 形式: 例如 'max-stale=10' 而不是 'max-stale="10"'. 发送方 MUST NOT 生成 quoted-string 形式.

5.2.1.3 min-fresh

参数语法:

delta-seconds (see Section 1.2.2)

min-fresh 请求指令表示客户端偏好新鲜生命周期不小于其当前年龄加上指定秒数的响应. 也就是说, 客户端希望响应至少在指定秒数内保持新鲜.

此指令使用参数语法的 token 形式: 例如 'min-fresh=20' 而不是 'min-fresh="20"'. 发送方 MUST NOT 生成 quoted-string 形式.

5.2.1.4 no-cache

no-cache 请求指令表示客户端偏好不在源服务器成功验证的情况下使用已存储响应来满足请求.

5.2.1.5 no-store

no-store 请求指令表示缓存 MUST NOT 存储此请求或其任何响应的任何部分. 此指令适用于私有缓存和共享缓存. 在此上下文中, "MUST NOT store" 表示缓存 MUST NOT 有意将信息存储在非易失性存储中, 并且 MUST 在转发后尽最大努力尽快从易失性存储中移除这些信息.

此指令不是确保隐私的可靠或充分机制. 特别是, 恶意或被攻破的缓存可能无法识别或遵守此指令, 通信网络也可能易受窃听.

注意, 如果包含此指令的请求由缓存满足, no-store 请求指令不适用于已经存储的响应.

5.2.1.6 no-transform

no-transform 请求指令表示客户端要求中介避免转换内容, 如 [HTTP] 第 7.7 节所定义.

5.2.1.7 only-if-cached

only-if-cached 请求指令表示客户端只希望获得已存储响应. 遵循此请求指令的缓存收到它时, SHOULD 以符合该请求其他约束的已存储响应进行响应, 或返回 504 (Gateway Timeout) 状态码.

5.2.2 响应指令 (Response Directives)

本节定义缓存响应指令. 缓存 MUST 遵守本节定义的 Cache-Control 指令.

5.2.2.1 max-age

参数语法:

delta-seconds (see Section 1.2.2)

max-age 响应指令表示当响应年龄大于指定秒数后, 该响应应被视为陈旧.

此指令使用参数语法的 token 形式: 例如 'max-age=5' 而不是 'max-age="5"'. 发送方 MUST NOT 生成 quoted-string 形式.

5.2.2.2 must-revalidate

must-revalidate 响应指令表示, 一旦响应变得陈旧, 在它按第 4.3 节定义由源服务器成功验证之前, 缓存 MUST NOT 重用该响应来满足另一个请求.

must-revalidate 指令对于支持某些协议特性的可靠运行是必要的. 在任何情况下, 缓存 MUST NOT 忽略 must-revalidate 指令; 特别是, 如果缓存处于断开连接状态, 缓存 MUST 生成错误响应, 而不是重用陈旧响应. 除非另一个错误状态码更适用, 生成的状态码 SHOULD 为 504 (Gateway Timeout).

服务器 SHOULD 仅在未能重新验证请求可能导致错误操作时使用 must-revalidate 指令 (例如静默未执行的金融交易).

must-revalidate 指令还使共享缓存能够重用对包含 Authorization 头字段的请求的响应 (见 [HTTP] 第 11.6.2 节), 但需满足上述重新验证要求 (第 3.5 节).

5.2.2.3 must-understand

must-understand 响应指令将响应的缓存限制为理解并符合该响应状态码要求的缓存.

包含 must-understand 指令的响应 SHOULD 同时包含 no-store 指令. 当实现 must-understand 指令的缓存收到包含该指令的响应时, 如果它理解并实现该状态码的缓存要求, 则 SHOULD 忽略 no-store 指令.

5.2.2.4 no-cache

参数语法:

#field-name

no-cache 响应指令的非限定形式 (无参数) 表示, 在转发该响应进行验证并收到成功响应之前, 该响应 MUST NOT 用于满足任何其他请求; 见第 4.3 节.

这允许源服务器防止缓存在未联系源服务器的情况下使用响应来满足请求, 即使这些缓存已被配置为发送陈旧响应.

no-cache 响应指令的限定形式带有列出一个或多个字段名的参数, 它表示在遵守任何其他缓存限制的前提下, 如果列出的头字段从后续响应中排除, 或后续响应已经由源服务器成功重新验证 (更新或移除这些字段), 则缓存 MAY 使用该响应来满足后续请求. 这允许源服务器防止响应中的某些头字段被重用, 同时仍允许缓存响应的其余部分.

给定的字段名不限于本规范定义的头字段集合. 字段名大小写不敏感.

此指令使用参数语法的 quoted-string 形式. 发送方 SHOULD NOT 生成 token 形式 (即使单项列表看起来不需要引号).

Note: 该指令的限定形式通常会被缓存当作收到非限定 no-cache 指令来处理; 即, 限定形式的特殊处理并未被广泛实现.

5.2.2.5 no-store

no-store 响应指令表示缓存 MUST NOT 存储直接请求或响应的任何部分, 且 MUST NOT 使用该响应来满足任何其他请求.

此指令适用于私有缓存和共享缓存. 在此上下文中, "MUST NOT store" 表示缓存 MUST NOT 有意将信息存储在非易失性存储中, 并且 MUST 在转发后尽最大努力尽快从易失性存储中移除这些信息.

此指令不是确保隐私的可靠或充分机制. 特别是, 恶意或被攻破的缓存可能无法识别或遵守此指令, 通信网络也可能易受窃听.

注意, must-understand 缓存指令在某些情况下会覆盖 no-store; 见第 5.2.2.3 节.

5.2.2.6 no-transform

no-transform 响应指令表示中介 (无论是否实现缓存) MUST NOT 转换内容, 如 [HTTP] 第 7.7 节所定义.

5.2.2.7 private

参数语法:

#field-name

非限定 private 响应指令表示共享缓存 MUST NOT 存储该响应 (即该响应面向单个用户). 它还表示, 即使该响应在其他情况下不会被私有缓存启发式缓存, 私有缓存也 MAY 在遵守第 3 节定义的约束下存储该响应.

如果存在限定 private 响应指令 (带有列出一个或多个字段名的参数), 则只有列出的头字段被限制为单个用户: 如果列出的头字段存在于原始响应中, 共享缓存 MUST NOT 存储这些头字段, 但 MAY 在不包含这些头字段的情况下存储响应消息的其余部分, 并遵守第 3 节定义的约束.

给定的字段名不限于本规范定义的头字段集合. 字段名大小写不敏感.

此指令使用参数语法的 quoted-string 形式. 发送方 SHOULD NOT 生成 token 形式 (即使单项列表看起来不需要引号).

Note: "private" 一词的这种用法只控制响应可以存储在哪里; 它不能确保消息内容的隐私. 此外, 该指令的限定形式通常会被缓存当作收到非限定 private 指令来处理; 即, 限定形式的特殊处理并未被广泛实现.

5.2.2.8 proxy-revalidate

proxy-revalidate 响应指令表示, 一旦响应变得陈旧, 在它按第 4.3 节定义由源服务器成功验证之前, 共享缓存 MUST NOT 重用该响应来满足另一个请求. 这类似于 must-revalidate (第 5.2.2.2 节), 只是 proxy-revalidate 不适用于私有缓存.

注意, proxy-revalidate 本身并不意味着响应可缓存. 例如, 它可以与 public 指令 (第 5.2.2.9 节) 组合, 允许响应被缓存, 同时只要求共享缓存在陈旧时重新验证.

5.2.2.9 public

public 响应指令表示, 即使在其他情况下响应会被禁止存储, 缓存也 MAY 在遵守第 3 节定义的约束下存储该响应. 换句话说, public 显式地将响应标记为可缓存. 例如, public 允许共享缓存重用对包含 Authorization 头字段的请求的响应 (第 3.5 节).

注意, 对于已经按第 3 节可缓存的响应, 不需要添加 public 指令.

如果带有 public 指令的响应没有显式新鲜度信息, 它是启发式可缓存的 (第 4.2.2 节).

5.2.2.10 s-maxage

参数语法:

delta-seconds (see Section 1.2.2)

s-maxage 响应指令表示, 对于共享缓存, 此指令指定的最大年龄会覆盖 max-age 指令或 Expires 头字段指定的最大年龄.

s-maxage 指令为共享缓存纳入 proxy-revalidate 响应指令 (第 5.2.2.8 节) 的语义. 在带有 s-maxage 的陈旧响应按第 4.3 节定义由源服务器成功验证之前, 共享缓存 MUST NOT 重用该响应来满足另一个请求. 此指令还允许共享缓存重用对包含 Authorization 头字段的请求的响应, 但需满足上述最大年龄和重新验证要求 (第 3.5 节).

此指令使用参数语法的 token 形式: 例如 's-maxage=10' 而不是 's-maxage="10"'. 发送方 MUST NOT 生成 quoted-string 形式.

5.2.3 扩展指令 (Extension Directives)

Cache-Control 头字段可以通过使用一个或多个扩展缓存指令进行扩展. 缓存 MUST 忽略无法识别的缓存指令.

信息性扩展 (即不要求改变缓存行为的扩展) 可以在不改变其他指令语义的情况下添加.

行为性扩展被设计为通过充当现有缓存指令基础之上的修饰符来工作. 新指令和旧指令会同时提供, 因而不理解新指令的应用会默认采用旧指令指定的行为, 而理解新指令的应用会识别出它修改了与旧指令关联的要求. 通过这种方式, 可以在不破坏已部署缓存的情况下扩展现有缓存指令.

例如, 考虑一个名为 "community" 的假想新响应指令, 它充当 private 指令的修饰符: 除私有缓存外, 仅由某个命名社区成员共享的任何缓存也允许缓存该响应. 希望允许 UCI 社区在其共享缓存中使用原本为 private 的响应的源服务器, 可以通过包含以下内容来实现:

Cache-Control: private, community="UCI"

识别这种 community 缓存指令的缓存可以按照该扩展扩展其行为. 不识别 community 缓存指令的缓存会忽略它并遵守 private 指令.

新的扩展指令应考虑定义:

  • 多次指定该指令意味着什么,

  • 当指令参数是可选的, 参数存在时以及参数不存在时分别意味着什么,

  • 当指令参数是必需的, 参数缺失时意味着什么, 以及

  • 该指令是特定于请求, 特定于响应, 还是可同时用于两者.

5.2.4 缓存指令注册表 (Cache Directive Registry)

"Hypertext Transfer Protocol (HTTP) Cache Directive Registry" 定义了缓存指令的命名空间. 它已经创建, 现在维护于 ````https://www.iana.org/assignments/http-cache-directives\````.

注册项 MUST 包含以下字段:

  • Cache Directive Name

  • Pointer to specification text

要添加到此命名空间的值需要 IETF Review (见 [RFC8126] 第 4.8 节).

5.3 Expires

"Expires" 响应头字段给出一个日期/时间, 在此之后响应被视为陈旧. 关于新鲜度模型的进一步讨论, 见第 4.2 节.

Expires 头字段的存在并不意味着原始资源会在该时间之前, 该时间或该时间之后发生变化或不复存在.

Expires 字段值是 HTTP-date 时间戳, 如 [HTTP] 第 5.6.7 节所定义. 关于缓存特定的解析要求, 另见第 4.2 节.

Expires = HTTP-date

例如:

Expires: Thu, 01 Dec 1994 16:00:00 GMT

缓存接收方 MUST 将无效日期格式, 尤其是值 "0", 解释为表示过去的时间 (即"已经过期").

如果响应包含带有 max-age 指令 (第 5.2.2.1 节) 的 Cache-Control 头字段, 接收方 MUST 忽略 Expires 头字段. 同样, 如果响应包含 s-maxage 指令 (第 5.2.2.10 节), 共享缓存接收方 MUST 忽略 Expires 头字段. 在任一情况下, Expires 中的值都只面向尚未实现 Cache-Control 头字段的接收方.

没有时钟的源服务器 (见 [HTTP] 第 5.6.7 节) MUST NOT 生成 Expires 头字段, 除非其值表示过去的固定时间 (始终过期), 或其值已由带有时钟的系统与资源关联.

历史上, HTTP 要求 Expires 字段值不得超过未来一年. 尽管更长的新鲜生命周期不再被禁止, 但已有证据表明极大的值会导致问题 (例如由于使用 32 位整数表示时间值而发生时钟溢出), 且许多缓存会更早地逐出响应.

5.4 Pragma

"Pragma" 请求头字段是为 HTTP/1.0 缓存定义的, 使客户端能够指定 "no-cache" 请求 (因为 Cache-Control 直到 HTTP/1.1 才被定义).

然而, 对 Cache-Control 的支持现在已经非常普遍. 因此, 本规范弃用 Pragma.

Note: 由于响应中 "Pragma: no-cache" 的含义从未被规定, 它不能作为响应中 "Cache-Control: no-cache" 的可靠替代.

5.5 Warning

"Warning" 头字段曾用于携带有关消息状态或转换的附加信息, 这些信息可能无法反映在状态码中. 本规范废止它, 因为它并未被广泛生成或呈现给用户. 它曾携带的信息可以通过检查其他头字段获得, 例如 Age.