使用Apache commons HttpClient时,如何覆盖请求中的“Host”标头

问题描述 投票:9回答:4

我正在使用Jakarta Commons HttpClient 3.1编写一个负载测试工具,该工具需要针对不同的服务器,并假装它针对HTTP服务器中的正确虚拟主机。为此,我需要能够将请求中的“主机”HTTP标头设置为不同的主机名,然后是我要连接的实际主机名。

很明显我应该使用Method.setRequestHeader("Host","fakehostname"),但HttpClient只是忽略了这一点,并且总是在“Host”标题中发送我正在连接的真实主机名(我已启用“httpclient.wire”的调试日志记录,我可以这是具体的)。

如何覆盖标题以便HttpClient注意?

java apache-commons-httpclient
4个回答
14
投票

在搜索了一些,并从Oleg的答案中得到了一个暗示后,我找到了HttpMethodParams::setVirtualHost()的方法。

当HttpClient格式化请求时,它总是在发送请求之前自己创建“主机”标头 - 因此它不能被覆盖为标准标头。但是,在从URL生成“Host”标头的主机名之前,HttpClient会检查HttpMethodParams对象以查看用户是否要覆盖主机名。这只会覆盖主机名而不是端口,所以它更容易使用,虽然不像我想的那样直观。

使用它的代码可能如下所示:

Method m = new GetMethod("http://some-site/some/path");
m.getParams().setVirtualHost("some-other-site");
client.executeMethod(m);

因为我喜欢一个衬垫,所以这也可以写成:

client.executeMethod(new GetMethod("http://some-site/some/path") {{
    getParams().setVirtualHost("some-other-site"); }});

4
投票

以下适用于android:

System.setProperty("sun.net.http.allowRestrictedHeaders", "true");
InputStream stream_content=null;
try
   {URL url=new URL("http://74.125.28.103/");
    HttpURLConnection conn=(HttpURLConnection)url.openConnection();
    conn.setDoOutput(true);
    conn.setRequestMethod("GET");
    conn.setRequestProperty("Host", "www.google.com");
    stream_content=conn.getInputStream();
   }
catch (Exception e) {}

对于https网址:

System.setProperty("sun.net.http.allowRestrictedHeaders", "true");
InputStream stream_content=null;
try
   {URL url=new URL("https://74.125.28.103/");
    HttpsURLConnection conn=(HttpsURLConnection)url.openConnection();
    conn.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER );
    conn.setDoOutput(true);
    conn.setRequestMethod("GET");
    conn.setRequestProperty("Host", "www.google.com");
    stream_content=conn.getInputStream();
   }
catch (Exception e) {}

3
投票

我相信你想要http://hc.apache.org/httpcomponents-core-ga/httpcore/apidocs/org/apache/http/HttpHost.html:这可以让你为特定连接配置主机。如果我理解正确,你可以使用execute方法(参见http://hc.apache.org/httpcomponents-client-ga/httpclient/apidocs/org/apache/http/impl/client/AbstractHttpClient.html#execute(org.apache.http.HttpHost,%20org.apache.http.HttpRequest))并传递一个自定义的HttpHost对象,或者这样做:

  1. 构造一个HttpHost实例,并将其传递给Host头。
  2. 用它来创建一个HttpRoute实例(参见http://hc.apache.org/httpcomponents-client-ga/httpclient/apidocs/org/apache/http/conn/routing/HttpRoute.html
  3. 请求连接时将其传递给连接管理器(请参阅http://hc.apache.org/httpcomponents-client-ga/httpclient/apidocs/org/apache/http/conn/ClientConnectionManager.html#requestConnection(org.apache.http.conn.routing.HttpRoute,%20java.lang.Object))。
  4. 使用与您的方法的连接:有关详细信息,请参阅http://hc.apache.org/httpcomponents-client-ga/tutorial/html/connmgmt.html

让我知道它是如何工作的。

编辑:原则保持不变。 1.构造一个HttpHost实例,将其传递给Host头(请参阅http://hc.apache.org/httpclient-legacy/apidocs/index.html?org/apache/commons/httpclient/HttpHost.html)。 2.创建一个HttpConfiguration实例,然后将它传递给你创建的HttpHost(参见http://hc.apache.org/httpclient-legacy/apidocs/index.html?org/apache/commons/httpclient/HostConfiguration.html)。 3.在具有该配置的HttpClient上使用execute方法(请参阅http://hc.apache.org/httpclient-legacy/apidocs/org/apache/commons/httpclient/HttpClient.html#executeMethod(org.apache.commons.httpclient.HostConfiguration,%20org.apache.commons.httpclient.HttpMethod))


2
投票

可以使用'http.virtual-host'参数来强制任意(虚拟)主机名和端口作为Host请求标头的值,而不是从实际请求URI派生的值。但这仅适用于4.x API。

© www.soinside.com 2019 - 2024. All rights reserved.