Problem
问题是使用了 Cache-Control 响应指令 Must-revalidate。
据我所知,通过省略必须重新验证,您已经拥有了用例的完美定义:
Cache-Control: max-age=86400, private
这控制所请求的资源被视为新鲜的时间。经过这段时间后,答案不应再直接来自缓存,而是应联系服务器以验证后续请求。在您的情况下,由于服务器提供 ETag,iOS 会向服务器发送带有 If-None-Match 标头的请求。
确认
为了检查这一点,我使用了没有 NSURLCache 设置的 testRestfulAPI 方法,并在服务器端配置了 60 秒的最大期限,因此我不必等待一天来检查结果。
之后,我每秒触发一次 testRestfulAPI。我总是从缓存中得到想要的结果。 Charles 表明数据必须来自缓存,因为 60 秒内没有联系服务器。
RFC 7234
以下是 RFC 7234(已废弃 RFC 2616)的引用,位于 5.2.2.1 下。它指出:
必须重新验证指令对于支持可靠的
某些协议功能的操作。在所有情况下都有缓存
必须遵守必须重新验证指令;特别是,如果缓存
由于任何原因无法到达源服务器,它必须生成 504
(网关超时)响应。
当且仅当服务器应该使用 Must-revalidate 指令
如果未能验证对表示的请求可能会导致
不正确的操作,例如默默地未执行的财务
交易。
阅读完本文后,如果您将自己置于缓存开发人员的角度,您可以很好地想象,当看到必须重新验证时,始终会联系原始服务器,并且任何其他指令(例如 max-age)都会被忽略。在我看来,缓存在实践中经常表现出这种行为。
5.2.2.1 章中还有一节。我不会隐瞒,内容如下:
“must-revalidate”响应指令表明,一旦它变得过时,缓存不得使用该响应来满足后续请求,而无需在源服务器上成功验证。
这通常被解释为通过指定 max-age 和 Must-revalidate ,您可以确定内容何时过时(在 max-age 秒之后),然后它必须在源服务器上进行验证,然后才能提供内容。
然而,在实践中,由于上述原因,必须重新验证似乎总是会导致对源服务器上的每个请求进行验证。