12

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

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

如何覆盖标头以便 HttpClient 注意到?

4

4 回答 4

15

在搜索了更多内容并从 Oleg 的回答中得到提示后,我找到了HttpMethodParams::setVirtualHost()方法。

当 HttpClient 格式化请求时,它总是在发送请求之前自己创建“Host”标头 - 因此它不能作为标准标头被覆盖。但在从 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"); }});
于 2011-05-20T18:29:46.837 回答
4

我相信您想要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. 使用execute具有该配置的 HttpClient 上的方法(请参阅http://hc.apache.org/httpclient-legacy/apidocs/org/apache/commons/httpclient/HttpClient.html#executeMethod(org.apache.commons.httpclient. HostConfiguration,%20org.apache.commons.httpclient.HttpMethod ))

于 2011-05-18T14:38:39.133 回答
3

以下适用于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) {}
于 2013-08-21T05:59:49.520 回答
2

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

于 2011-05-18T15:09:22.090 回答