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

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

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

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

在搜索了一些,并从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"); }}); 

以下适用于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) {} 

对于httpsurl:

 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) {} 

我相信你想要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 ))

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