Как я могу переопределить заголовок Host в запросе при использовании Apache commons HttpClient

Я использую Jakarta Commons HttpClient 3.1, пишу инструмент нагрузочного тестирования, который должен ориентироваться на разные серверы и делать вид, что он нацелен на правильный виртуальный хост на HTTP-сервере. Для этого мне нужно иметь возможность установить HTTP-заголовок «Host» в запросе на другое имя хоста, чем фактическое имя хоста, к которому я подключаюсь.

Казалось довольно очевидным, что я должен использовать Method.setRequestHeader("Host","fakehostname"), но HttpClient просто игнорирует это и всегда отправляет реальное имя хоста, к которому я подключаюсь, в заголовке «Host» (я включил ведение журнала отладки для «httpclient.wire», и я могу это делает это специально).

Как я могу переопределить заголовок, чтобы HttpClient прислушался?


person Guss    schedule 18.05.2011    source источник


Ответы (4)


После еще нескольких поисков и получения подсказки от ответа Олега я нашел метод HttpMethodParams::setVirtualHost().

когда HttpClient форматирует запрос, он всегда создает сам заголовок «Host» непосредственно перед отправкой запроса, поэтому его нельзя переопределить как стандартный заголовок. Но прежде чем из 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"); }});
person Guss    schedule 20.05.2011

Следующие работы на андроиде:

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

для https URL:

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) {}
person diyism    schedule 21.08.2013
comment
В этом решении используется встроенный HTTP-клиент Java (см. пространство имен свойства sun.net.http), и я ожидаю, что оно будет работать во всех реализациях Java, хотя мне это бесполезно, поскольку я использую HTTP-клиент Apache commons. . - person Guss; 14.09.2014

Думаю, вам нужен 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. Используйте метод execute для HttpClient с этой конфигурацией (см. apache.commons.httpclient.HostConfiguration,%20org.apache.commons.httpclient.HttpMethod" rel="nofollow">http://hc.apache.org/httpclient-legacy/apidocs/org/apache/commons/httpclient/HttpClient .html#executeMethod(org.apache.commons.httpclient.HostConfiguration,%20org.apache.commons.httpclient.HttpMethod))

person Femi    schedule 18.05.2011
comment
Я использую HttpClient 3.1, а не HttpComponents. Извините, что не упомянул об этом раньше. Я отредактировал свой вопрос, чтобы сделать его более понятным. - person Guss; 19.05.2011

Можно использовать параметр 'http.virtual-host', чтобы указать произвольное (виртуальное) имя хоста и порт в качестве значения заголовка запроса Host вместо тех, которые получены из фактического URI запроса. Однако это работает только с API 4.x.

person ok2c    schedule 18.05.2011