OkHttp客户端不尊重Accept标头

时间:2016-12-13 15:24:10

标签: java json okhttp

使用相同的url和不同的accept标头发出请求会从okhttp cache返回先前的响应。

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

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

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

有没有人遇到过这个问题?

1 个答案:

答案 0 :(得分:2)

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

  

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

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()方法中使用断点进行调试,然后逐步查看是否/何时出错。如果是,请与维护人员一起提交或提交补丁。