【问题标题】:OkHttp client does not respect Accept headerOkHttp 客户端不尊重 Accept 标头
【发布时间】:2017-04-28 17:25:17
【问题描述】:

使用相同的 url 和不同的接受标头发出请求会返回来自 okhttp 缓存的先前响应。

这意味着第一个请求是针对 application/json 数据,第二个请求是 application/xml。因此,客户端从缓存中返回 json 数据,而不是在上游执行 xml。

例如 GET 请求:http://example.com 带有标头 application/json 返回 Cache-Control 标头和 json 有效负载。 响应被缓存在内部 http 缓存中。 第二个请求是在缓存控制窗口中向http://example.com 发出的,带有标头 application/xml。在这种情况下,Okhttp 从缓存中返回相同的 json 有效负载,而不是 xml 有效负载。

Builder builder = new Builder().url("https://httpbin.org/headers").header("accept", header);

有人遇到过这个问题吗?

【问题讨论】:

  • 也许给我们展示一小段代码及其输出,证明问题?
  • gist.github.com/gpor89/c69c795b334af5ff63cef6468222a01e 但该资源的测试通过了,因为该站点不返回缓存标头。
  • 不是重点。问题应该是独立的。你不需要整个代码,只要人们可以看到你在做什么——并显示你的输出就足够了。

标签: java json okhttp


【解决方案1】:

描述缓存应该如何工作的相关 RFC 在此处:https://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13.6

如果缓存条目的选择请求头字段与新请求的选择请求头字段不匹配,则缓存不得使用缓存条目来满足请求,除非它首先将新请求中继到源服务器在条件请求中,服务器以 304(未修改)响应,包括指示要使用的实体的实体标签或 Content-Location。

OkHttp 的Cache 的源代码在这里:https://github.com/square/okhttp/blob/master/okhttp/src/main/java/okhttp3/Cache.java

缓存键就是资源的 URL。但是缓存条目也会与“变化”的请求标头进行比较:

Response response = entry.response(snapshot);

if (!entry.matches(request, response)) {
  Util.closeQuietly(response.body());
  return null;
}

...

public boolean matches(Request request, Response response) {
  return url.equals(request.url().toString())
      && requestMethod.equals(request.method())
      && HttpHeaders.varyMatches(response, varyHeaders, request);
}

当然,您可能发现了一个错误。我建议引入 OkHttp 源 JAR,在 Cache.get() 方法中使用断点进行调试,然后逐步查看是否/何时出错。如果是,请向维护者提出或提交补丁。

【讨论】:

  • key 只是 URL,但它在决定是否返回缓存的响应时会考虑存储响应和传入请求的标头。
  • @JesseWilson 啊,仔细一看,确实如此。
  • @JesseWilson 相应地改变了答案。
猜你喜欢
  • 2015-08-26
  • 1970-01-01
  • 2017-04-15
  • 1970-01-01
  • 2019-08-07
  • 2023-01-26
  • 1970-01-01
  • 2017-02-20
  • 2019-04-11
相关资源
最近更新 更多