我正在使用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标头的任何建议吗?非常感谢!
答案 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来破解它。