对 HTTPS 主机的 HttpClient 请求转到默认名称服务器

HttpClient request to HTTPS host goes to default nameserver

我在 android 项目中使用 Apache httpClient 库向服务器发送 get/post 请求。我的服务器是使用 apache namevirtualhost 设置的 - 同一台服务器上有多个虚拟主机。

对于那些不熟悉 apache namevirtualhost 工作原理的人来说,简单的解释就是在 server config 中定义了多个配置,apache 使用 Host request header 来确定使用哪个配置.当定义了多个主机时,第一个被认为是默认的,所有 Host 请求 header 未明确匹配定义的名称虚拟主机之一的请求将使用默认配置处理。

现在,我尝试连接的服务器不是默认服务器。当我的应用程序运行并向服务器发出请求时,它不会转到我的虚拟主机,而是由默认主机处理,导致证书名称不匹配。 (请注意,我确实设置了正确的证书。)

这是我的代码 - copy/paste,除了实际的 URL:

String targetUrl = getTargetUrl();
//this returns something like https://www.example.com/api/1/orders (without spaces, of course)
HttpClient client = new DefaultHttpClient();
HttpPost post = new HttpPost(targetUrl);

List<NameValuePair> data = new ArrayList<NameValuePair>(1);
data.add(new BasicNameValuePair("orders", json.toString()));
data.add(new BasicNameValuePair("username", username));
data.add(new BasicNameValuePair("password", password));
post.setEntity(new UrlEncodedFormEntity(data));
HttpResponse response = client.execute(post);

这会导致出现一条错误消息,指出证书名称与请求的 url 不匹配,并显示请求的 url 和证书 url - 证书 url 是 apache 配置中的默认设置。

我在执行请求的行之前添加了这段代码:

Header[] hds = post.getAllHeaders();
for(Header h : hds) {
    Log.d("PasteneOrers", h.getName() + ": " + h.getValue());
}

查看包含哪些 header。有趣的是,Host header 没有显示。然后我在执行请求之前添加了这段代码:

URL url = new URL(targetUrl);
post.setHeader("Host", url.getHost());

现在上面的调试输出正确显示了 Host header - 但它没有帮助,请求仍然是默认的。

为了验证这不是服务器配置错误的问题,我复制了目标 URL 并将其粘贴到同一个 android 模拟器上的浏览器 运行 - 这有效正确,我得到正确的结果。因此它肯定是我的代码中的东西 - 但是什么?在这一点上我被卡住了。如有任何建议,我们将不胜感激。

为了其他人遇到这个问题,我无法用 apache httpclient 解决它。我改用 HttpUrlConnection 并且一切正常。