简体   繁体   English

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

[英]How can I override the “Host” header in the request when using Apache commons HttpClient

I am using Jakarta Commons HttpClient 3.1 writing a load test tool that needs to target different servers and pretend like it targeted the correct virtual host in the HTTP server. 我正在使用Jakarta Commons HttpClient 3.1编写一个负载测试工具,该工具需要针对不同的服务器,并假装它针对HTTP服务器中的正确虚拟主机。 For that I need to be able to set the "Host" HTTP header in the request to a different host name then the actual host name that I'm connecting to. 为此,我需要能够将请求中的“主机”HTTP标头设置为不同的主机名,然后是我要连接的实际主机名。

It seemed pretty obvious that I should use Method.setRequestHeader("Host","fakehostname") , but HttpClient just ignores this and always sends the real host name I'm connecting to in the "Host" header (I've enabled debug logging for "httpclient.wire" and I can it does this specifically). 很明显我应该使用Method.setRequestHeader("Host","fakehostname") ,但是HttpClient只是忽略了这一点,并且总是在“Host”头中发送我正在连接的真实主机名(我启用了调试)记录“httpclient.wire”,我可以这样做具体)。

How can I override the header so that HttpClient takes heed? 如何覆盖标题以便HttpClient注意?

After searching some more, and taking a hint from Oleg's answer, I've found the method HttpMethodParams::setVirtualHost() . 在搜索了一些,并从Oleg的答案中得到了一个提示之后,我找到了方法HttpMethodParams :: setVirtualHost()

when HttpClient formats a request, it always creates the "Host" header itself just before sending the request - so it cannot be overridden as a standard header. 当HttpClient格式化请求时,它总是在发送请求之前自己创建“主机”标头 - 因此它不能被覆盖为标准标头。 But before the host name for the "Host" header is generated from the URL, HttpClient checks the HttpMethodParams object to see if the user wants to override the host name. 但是,在从URL生成“Host”标头的主机名之前,HttpClient会检查HttpMethodParams对象以查看用户是否要覆盖主机名。 This only overrides the host name and not the port so it would be easier to use, though not as intuitive as I'd like. 这只会覆盖主机名而不是端口,所以它更容易使用,虽然不像我想的那样直观。

The code to use this can look like this: 使用它的代码可能如下所示:

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

Because I like one liners, this can also be written as: 因为我喜欢一个衬垫,所以这也可以写成:

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

Following works on android: 以下适用于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) {}

for https url: 对于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) {}

I believe you want http://hc.apache.org/httpcomponents-core-ga/httpcore/apidocs/org/apache/http/HttpHost.html : this lets you configure the host for a specific connection. 我相信你想要http://hc.apache.org/httpcomponents-core-ga/httpcore/apidocs/org/apache/http/HttpHost.html :这可以让你为特定连接配置主机。 If I understand it correctly, you can either use the execute method (see 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 )) and pass it a custom HttpHost object, or do this: 如果我理解正确,你可以使用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. Construct an HttpHost instance, passing it your Host header. 构造一个HttpHost实例,并将其传递给Host头。
  2. Use that to create an HttpRoute instance (see http://hc.apache.org/httpcomponents-client-ga/httpclient/apidocs/org/apache/http/conn/routing/HttpRoute.html ) 用它来创建一个HttpRoute实例(参见http://hc.apache.org/httpcomponents-client-ga/httpclient/apidocs/org/apache/http/conn/routing/HttpRoute.html
  3. Pass that to the connection manager when you request a connection (see 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 )). 请求连接时将其传递给连接管理器(请参阅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. Use the connection with your method: see http://hc.apache.org/httpcomponents-client-ga/tutorial/html/connmgmt.html for more details. 使用与您的方法的连接:有关详细信息,请参阅http://hc.apache.org/httpcomponents-client-ga/tutorial/html/connmgmt.html

Let me know how that works. 让我知道它是如何工作的。

EDIT: principle remains the same. 编辑:原则保持不变。 1. Construct an HttpHost instance, passing it your Host header (see http://hc.apache.org/httpclient-legacy/apidocs/index.html?org/apache/commons/httpclient/HttpHost.html ). 1.构造一个HttpHost实例,将其传递给Host头(请参阅http://hc.apache.org/httpclient-legacy/apidocs/index.html?org/apache/commons/httpclient/HttpHost.html )。 2. Create an HttpConfiguration instance and then pass it the HttpHost you created (see http://hc.apache.org/httpclient-legacy/apidocs/index.html?org/apache/commons/httpclient/HostConfiguration.html ). 2.创建一个HttpConfiguration实例,然后将其传递给您创建的HttpHost(请参阅http://hc.apache.org/httpclient-legacy/apidocs/index.html?org/apache/commons/httpclient/HostConfiguration.html )。 3. Use the execute method on HttpClient with that configuration (see 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.使用具有该配置的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 ))

One can use the 'http.virtual-host' parameter in order to force an arbitrary (virtual) hostname and port as a value of the Host request header instead of those derived from the actual request URI. 可以使用'http.virtual-host'参数来强制任意(虚拟)主机名和端口作为Host请求标头的值,而不是从实际请求URI派生的值。 This works with the 4.x API only, though. 但这仅适用于4.x API。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 使用org.apache.commons.httpclient时,我可以在命令行上设置代理吗? - Can I set the proxy on the command line when using org.apache.commons.httpclient? 如何将安全性Cookie传递到HttpClient Get请求(Apache Commons) - How to pass security cookies into a HttpClient Get request (Apache Commons) 在Java中,在发送JSON POST时使用HttpPost(apache commons HttpClient) - 我应该对身体进行URL编码吗? - In Java, using HttpPost (apache commons HttpClient) when sending JSON POST - should I URL encode the body? 我可以在没有Commons-logging.jar的情况下使用Apache HTTPClient - Can I use Apache HTTPClient without Commons-logging.jar 如何使用Apache Commons Net写入远程文件? - How can I write to a remote file using Apache Commons Net? 如何从apache httpclient 4中禁用默认请求标头? - How can I disable default request headers from apache httpclient 4? 如何使用HttpURLConnection以与Apache HttpClient lib相同的方式发出POST请求 - How can I make a POST request in the same manner as Apache HttpClient lib, using HttpURLConnection org.apache.commons.httpclient.HttpClient卡在请求上 - org.apache.commons.httpclient.HttpClient stuck on request 使用Apache Commons HttpClient上传SmbFile - Uploading SmbFile using Apache Commons HttpClient 如何为Apache Commons httpclient注册URL处理程序 - how to register url handler for apache commons httpclient
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM