【发布时间】:2021-04-21 11:08:30
【问题描述】:
我们看到一些行为,我们没有在 OkHttp 中缓存响应,并最终每次都访问服务器。但是,响应在未来有一个 Expires 时间,所以理想情况下它会被缓存。
这是我们在响应中看到的标头的一个简单示例(请求已发送,响应已在 Sat, 16 Jan 2021 00:40:36 GMT 接收):
date: Sat, 16 Jan 2021 00:40:36 GMT
age: 6
expires: Sat, 16 Jan 2021 00:40:40 GMT
last-modified: Sat, 16 Jan 2021 00:40:30 GMT
根据我从 CacheStrategy 中看到的情况,问题在于它将日期 + 年龄相加,以查看它是否超过了到期时间。在这种情况下,00:40:36 + 6 = 00:40:42 > 00:40:40,所以它最终不会被添加到缓存中。
所以我认为理想情况下,响应日期将等于最后修改日期(在本例中为 2021 年 1 月 16 日星期六 00:40:30 GMT),或者我们需要有一个自定义 CacheStrategy 才能使用 last-修改而不是这些计算的日期。
如果有人对我是否做出任何错误假设有任何见解,或者上述选项之一是否更可取,请告诉我。我查看了日期/年龄标题的一些规范,我有点不清楚在这种情况下它们应该是什么。
我还发现调试 OkHttp 中的缓存行为有点困难,现在我一直在使用条件断点来尝试跟踪它,但如果有人有更好的想法,我也会很感激.
【问题讨论】:
-
您是否考虑过使用网络拦截器将合成缓存标头添加到响应中?或者考虑向请求添加一个 max-stale 缓存控制标头。
-
考虑包括缓存日志输出。 square.github.io/okhttp/caching square.github.io/okhttp/events 您可以显示缓存事件,或输出缓存对象类型或相关的原始标头。我想了解那里是否缺少一些可以更容易推理的东西。
-
就标头而言,我们不会在请求中发送任何缓存控制标头,我们会发送一个 etag,但理想情况下,如果之前的响应仍然存在,我们甚至不会访问网络有效的。除了我示例中的 4 个标头之外,我们在响应中返回的唯一其他相关标头是
cache-control: public, stale-while-revalidate=1, stale-if-error=86400。 -
在我们的请求中发送额外的缓存控制标头并不理想;在我们的例子中,我们实际上想要全天不同级别的缓存。因此,同一端点可能会返回有效期为 2 小时的响应,但稍后会返回仅有效期为 10 秒的响应。理想情况下,这是由服务器驱动的。我们尝试使用网络拦截器从响应中删除
age标头,这似乎以我们期望的方式缓存,但如果是这样的话,我很惊讶发现关于这个主题的讨论很少 -
对我们来说,当我们用我们的请求访问 cloudflare 时,就会出现这个问题。基本上,cloudflare 缓存来自源服务器的响应,在响应中附加
age标头,但似乎总是用当前时间覆盖date标头。如果我们跳过 cloudflare 并直接访问我们的源服务器,缓存似乎按我们预期的方式工作。但是,是的,我不是 HTTP 协议方面的专家,所以我不确定这是否是 cloudflare 或 okhttp 的问题,或者我们是否需要为其添加自定义逻辑(例如,通过删除年龄标头,或者添加响应中缓存控件的 max-age
标签: android http-headers okhttp cloudflare cache-control