[英]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
对象,或者这样做:
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.