3. 在缓存中存储响应 (Storing Responses in Caches)
缓存必须不(MUST NOT)存储对任何请求的响应,除非:
- 缓存理解该请求方法,并且该方法被定义为可缓存,并且
- 缓存理解该响应状态码,并且
- 请求或响应头字段中没有出现 "no-store" 缓存指令(见第 5.2 节),并且
- 如果缓存是共享缓存,响应中没有出现 "private" 响应指令(见第 5.2.2.6 节),并且
- 如果缓存是共享缓存,请求中没有出现 Authorization 头字段(见 [RFC7235] 的第 4.2 节),除非响应明确允许(见第 3.2 节),并且
- 响应满足以下任一条件:
- 包含 Expires 头字段(见第 5.3 节),或
- 包含 max-age 响应指令(见第 5.2.2.8 节),或
- 包含 s-maxage 响应指令(见第 5.2.2.9 节)且缓存是共享缓存,或
- 包含允许其被缓存的缓存控制扩展(Cache-Control Extension,见第 5.2.3 节),或
- 具有被默认定义为可缓存的状态码(见第 4.2.2 节),或
- 包含 public 响应指令(见第 5.2.2.5 节)。
注意,上面列出的任何要求都可以被缓存控制扩展覆盖;见第 5.2.3 节。
在此上下文中,如果缓存识别某个请求方法或响应状态码,并实现了所有指定的缓存相关行为,则称缓存已经"理解"(understood)该方法或状态码。
注意,在正常运行中,某些缓存不会存储既没有缓存验证器(cache validator)也没有显式过期时间的响应,因为此类响应通常存储价值不大。但是,缓存并未被禁止存储此类响应。
3.1. 存储不完整响应 (Storing Incomplete Responses)
当消息成帧([RFC7230])指示的所有八位组(octets)都在连接关闭前收到时,响应消息被认为是完整的。如果请求方法是 GET,响应状态码是 200(OK),并且已经收到整个响应头节区(response header section),则缓存可以(MAY)存储不完整的响应消息体,前提是缓存条目被记录为不完整。同样地,206(Partial Content)响应可以(MAY)像不完整的 200(OK)缓存条目一样被存储。但是,如果缓存不支持 Range 和 Content-Range 头字段,或者不理解这些字段中使用的范围单位(range units),缓存必须不(MUST NOT)存储不完整的或局部内容的响应。
缓存可以(MAY)通过发起后续的 range 请求([RFC7233])并将成功的响应与存储的条目按第 3.3 节的定义组合,来补全已存储的不完整响应。缓存必须不(MUST NOT)使用不完整响应来回答请求,除非该响应已被补全,或者该请求是部分的且指定的范围完全位于该不完整响应之内。缓存必须不(MUST NOT)在未使用 206(Partial Content)状态码明确标记的情况下向客户端发送部分响应。
3.2. 存储已认证请求的响应 (Storing Responses to Authenticated Requests)
对于带有 Authorization 头字段([RFC7235] 的第 4.2 节)的请求,共享缓存必须不(MUST NOT)使用其缓存的响应该请求来满足任何后续请求,除非响应中存在允许存储此类响应的缓存指令。
在本规范中,以下缓存控制响应指令(第 5.2.2 节)具有这种效果:must-revalidate、public 和 s-maxage。
注意,包含 "must-revalidate" 和/或 "s-maxage" 响应指令的缓存响应不允许由共享缓存以陈旧(stale)形式提供(第 4.2.4 节)。特别是,带有 "max-age=0, must-revalidate" 或 "s-maxage=0" 的响应不能用于满足后续请求,而必须先在源服务器上重新验证。
3.3. 合并部分内容 (Combining Partial Content)
如果连接过早关闭,或者请求使用了一个或多个 Range 说明符(Range specifiers,[RFC7233]),响应可能只传输部分表示(partial representation)。在多次此类传输之后,缓存可能已经收到了同一表示的多个范围。如果这些范围全部共享同一个强验证器(strong validator),且缓存遵守 [RFC7233] 第 4.3 节中的客户端要求,缓存可以(MAY)将这些范围合并为单个存储的响应,并重用该响应来满足后续的请求。
将新响应与一个或多个已存储的响应合并时,缓存必须(MUST):
- 删除已存储响应中 warn-code 为 1xx 的任何 Warning 头字段(见第 5.5 节);
- 保留已存储响应中 warn-code 为 2xx 的任何 Warning 头字段;并且
- 使用新响应中提供的其他头字段(Content-Range 除外)替换已存储响应中对应头字段的所有实例。