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

时间:2011-05-18 13:57:15

标签: java apache-commons-httpclient

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

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

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

4 个答案:

答案 0 :(得分: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"); }});

答案 1 :(得分: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) {}

答案 2 :(得分: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
  5. 让我知道它是如何运作的。

    编辑:原则保持不变。 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))

答案 3 :(得分:2)

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