java 使用 Apache commons HttpClient 时如何覆盖请求中的“主机”标头

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6045911/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 14:06:37  来源:igfitidea点击:

How can I override the "Host" header in the request when using Apache commons HttpClient

javaapache-commons-httpclient

提问by Guss

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. 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.

我正在使用 Jakarta Commons HttpClient 3.1 编写一个负载测试工具,该工具需要针对不同的服务器并假装它针对 HTTP 服务器中的正确虚拟主机。为此,我需要能够将请求中的“主机”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 只是忽略了这一点,并且总是在“主机”标头中发送我正在连接的真实主机名(我已经为“httpclient.wire”启用了调试日志记录,我可以这样做这特别)。

How can I override the header so that HttpClient takes heed?

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

回答by Guss

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. 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. 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.

当 HttpClient 格式化请求时,它总是在发送请求之前自己创建“Host”标头 - 因此它不能被覆盖为标准标头。但在从 URL 生成“Host”标头的主机名之前,HttpClient 检查 HttpMethodParams 对象以查看用户是否想要覆盖主机名。这只会覆盖主机名而不是端口,因此使用起来会更容易,但不如我想要的那么直观。

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"); }});

回答by diyism

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

回答by Femi

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. If I understand it correctly, you can either use the executemethod (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 HttpHostobject, or do this:

我相信您想要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. Construct an HttpHost instance, passing it your Host header.
  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)
  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)).
  4. Use the connection with your method: see http://hc.apache.org/httpcomponents-client-ga/tutorial/html/connmgmt.htmlfor more details.
  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

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). 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). 3. Use the executemethod 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))

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

回答by ok2c

One can use the 'http.virtual-host'parameter in order to force an arbitrary (virtual) hostname and port as a value of the Hostrequest header instead of those derived from the actual request URI. This works with the 4.x API only, though.

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