在okhttp请求

时间:2016-03-07 01:39:06

标签: android okhttp

我正在使用okhttp从我的Android APK发送一些http请求。由于某些服务器端代理要求,我希望url端点类似于:“https://api.example.com”,但是在http请求中,我想将HOST标头覆盖为“Host:proxy.example”。 COM”。我尝试使用类似的东西:

    HttpUrl url = new HttpUrl.Builder()
      .scheme("https")
      .host("api.example.com")
      .build();

    okhttprequest = new com.squareup.okhttp.Request.Builder()
      .url(url)
      .method("GET", requestBody)
      .header("Host", "proxy.example.com")
      .build();

    response = mOkHttpClient.newCall(okhttprequest).execute();

但是,当我查看网络包中的http请求时,HOST头仍然是“api.example.com”。只是想知道,我可以覆盖HOST标头的任何建议吗?非常感谢!

2 个答案:

答案 0 :(得分:1)

我有类似的问题。这就是我应用于您的情况的方式:

import javax.net.ssl.HttpsURLConnection;
import okhttp3.Dns;
import okhttp3.OkHttpClient;

OkHttpClient mOkHttpClient= new OkHttpClient.Builder()
            .dns(hostname -> {
                if(hostname.equals("proxy.example.com"))
                    hostname = "api.example.com";
                return Dns.SYSTEM.lookup(hostname);
            })
            .hostnameVerifier((hostname, session) -> {
                if(hostname.equals("proxy.example.com"))
                    return true;
                return HttpsURLConnection.getDefaultHostnameVerifier().verify(hostname, session);
            }).build();

然后像这样更新您的代码:

  HttpUrl url = new HttpUrl.Builder()
      .scheme("https")
      //.host("api.example.com") don't use this host
      .host("proxy.example.com") // use the one in the host header
      .build();

okhttprequest = new com.squareup.okhttp.Request.Builder()
  .url(url)
  .method("GET", requestBody)
  //.header("Host", "proxy.example.com") don't need anymore
  .build();

response = mOkHttpClient.newCall(okhttprequest).execute();

问题出在哪里,该解决方案如何工作:

您希望在主机标头中使用“ proxy.example.com”,但是okhttp还会使用在给定URL(在您的情况下为“ api.example.com”)中找到的标头创建此标头。

我找不到阻止okhttp这样做的方法。存在另一种方式。

我们在URL中使用“ proxy.example.com”,以便okhttp创建的主机标头将是“ host:proxy.example.com”,然后我们还为DNS查找添加了特殊情况。

在DNS解析为“ proxy.example.com”期间,我们将主机更改为“ api.example.com”,以便您的请求将以“ api.example.com”指向的IP地址发送到服务器。

这会产生副作用。服务器返回的证书将包含名称“ api.example.com”,并且由于URL中的主机是“ proxy.example.com”,因此主机名验证将失败。

为防止这种情况,我们为“ proxy.example.com”的验证添加了一种特殊情况,如果验证期间主机名为“ proxy.example.com”,则返回true。

'

答案 1 :(得分:0)

默认情况下,OkHttp不允许您设置与URL主机不同的主机头。您可以使用设置主机标头的network interceptor来破解它。