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

Guss picture Guss · May 18, 2011 · Viewed 17.3k times · Source

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.

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

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

Answer

Guss picture Guss · May 20, 2011

After searching some more, and taking a hint from Oleg's answer, I've found the method 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.

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