HTTP 从一开始就被设计成可以被广泛代理和缓存的。在允许的情况下,中间代理和客户端本身对 HTTP 进行缓存都是可以预期的。这是 HTTP 能够高扩展性的一个基本设计点。
这意味着,只要响应被定义为可缓存的,无论出于何种原因,服务器实现都应该假定这些响应会被缓存。如果服务器没有指定可缓存响应的适当 Cache-Control 指令,它可能永远不会收到后续请求。
以下 HTTP 方法被定义为可缓存:HEAD、GET 和 POST RFC 7231 (第 4.2.3 节)。
返回以下状态码之一的请求被定义为可缓存:200、203、204、206、300、301、404、405、410、414 和 501 RFC 7231 (第 6.1 节)。
一个常见的误解是,通过安全 HTTP 连接发出的请求由于安全原因不会被缓存。事实上,HTTP 规范中没有对 https 进行任何例外处理,缓存的工作方式与非加密 HTTP 完全相同。大多数现代浏览器对安全连接应用相同的缓存算法。
大多数 Python HTTP 客户端库在缓存方面非常保守,因此在使用这些客户端时,一整类完全有效的 RFC 缓存不会被观察到。假设“它在 Python 工具链中有效”并不意味着它在所有情况下都有效,也不是实现 HTTP 的唯一方法。我们预计浏览器中的 JavaScript 客户端将具有与现有 Python 客户端完全不同的缓存语义(这些语义完全符合 RFC)。
在 OpenStack API 中实现任何内容时,仔细考虑缓存语义对于 API 与现有各种运行时、编程语言和代理服务器(开放的和商业的)的兼容性至关重要。
鉴于上述内容(“缓存[...]是可以预期的”),服务必须提供适当的Cache-Control头,以避免像 1747935 中描述的错误,其中一个中间代理无限期地缓存响应,尽管底层资源发生了变化。
为了避免这个问题,至少,被上述定义为“可缓存”且没有其他方式控制缓存的响应,必须包含一个
Cache-Control: no-cache
尽管听起来是这样,no-cache(由 RFC 7234 定义) 仅意味着在可以针对源服务器验证的情况下才使用缓存资源。但是,如果没有可以发送回服务器的If-Modified-Since或者If-None-Match条件请求,no-cache则意味着不会发生缓存。有关验证的更多信息,请参见 RFC 7234。
这意味着至少所有返回GET状态码的请求200都需要该头,除非响应中明确表达了缓存要求。
MDN 提供了对 Cache-Control 头 的良好概述,并提供了一些关于指示期望缓存的方法的指导。如果期望缓存,除了Cache-Control头之外,还必须存在诸如ETag或者Last-Modified之类的头。
描述如何进行缓存验证和条件请求处理超出了这些指南的范围,因为要求会因服务而异。