2011-05-18 22 views
7

Estoy usando Jakarta Commons HttpClient 3.1 escribiendo una herramienta de prueba de carga que necesita apuntar a diferentes servidores y pretender que apunta al host virtual correcto en el HTTP servidor. Para eso necesito poder configurar el encabezado HTTP "Host" en la solicitud a un nombre de host diferente, luego el nombre de host real al que me estoy conectando.Cómo puedo anular el encabezado "Host" en la solicitud cuando uso recursos comunes de Apache HttpClient

Parecía bastante obvio que debería usar Method.setRequestHeader("Host","fakehostname"), pero HttpClient simplemente ignora esto y siempre envía el nombre de host real al que me estoy conectando en el encabezado "Host" (He habilitado el registro de depuración para "httpclient.wire" y puedo hacerlo específicamente).

¿Cómo puedo anular el encabezado para que HttpClient preste atención?

Respuesta

12

Después de buscar un poco más, y tomando una pista de la respuesta de Oleg, encontré el método HttpMethodParams::setVirtualHost().

cuando HttpClient formatea una solicitud, siempre crea el encabezado "Host" justo antes de enviar la solicitud, por lo que no se puede anular como encabezado estándar. Pero antes de que el nombre de host para el encabezado "Host" se genere a partir de la URL, HttpClient verifica el objeto HttpMethodParams para ver si el usuario desea anular el nombre de host. Esto solo anula el nombre de host y no el puerto, por lo que sería más fácil de usar, aunque no tan intuitivo como me gustaría.

El código para utilizar este puede tener este aspecto:

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

Creo que quiere http://hc.apache.org/httpcomponents-core-ga/httpcore/apidocs/org/apache/http/HttpHost.html: esto le permite configurar el host para una conexión específica. Si he entendido bien, puede utilizar el método execute (ver 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)) y pasarle un objeto personalizado HttpHost, o hacer esto:

  1. Construir una instancia HttpHost, pasándole el encabezado de host.
  2. la usará para crear una instancia HttpRoute (ver http://hc.apache.org/httpcomponents-client-ga/httpclient/apidocs/org/apache/http/conn/routing/HttpRoute.html)
  3. Pass que el administrador de conexión cuando se solicita una conexión (ver 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. Usa la conexión con tu método: mira http://hc.apache.org/httpcomponents-client-ga/tutorial/html/connmgmt.html para más detalles.

Dejarme saber cómo funciona eso.

EDITAR: el principio sigue siendo el mismo. 1. Construya una instancia de HttpHost, pasando su encabezado de host (vea http://hc.apache.org/httpclient-legacy/apidocs/index.html?org/apache/commons/httpclient/HttpHost.html). 2. Cree una instancia de HttpConfiguration y luego pase el HttpHost que creó (consulte http://hc.apache.org/httpclient-legacy/apidocs/index.html?org/apache/commons/httpclient/HostConfiguration.html). 3. utilizar el método execute en HttpClient con esa configuración (ver http://hc.apache.org/httpclient-legacy/apidocs/org/apache/commons/httpclient/HttpClient.html#executeMethod(org.apache.commons.httpclient.HostConfiguration,%20org.apache.commons.httpclient.HttpMethod))

+0

estoy usando HttpClient 3.1, no HttpComponents. Perdón, no lo mencioné antes. He editado mi pregunta para que quede más clara. – Guss

2

Uno puede usar el parámetro 'http.virtual-host' con el fin de forzar a un nombre de host arbitraria (virtual) y el puerto como un valor de la cabecera de Host petición en lugar de las derivado del URI de solicitud real. Sin embargo, esto solo funciona con la API 4.x.

+0

Lástima, estoy usando 3.1. – Guss

3

siguiente funciona en 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) {} 

de 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) {} 
+0

Esta solución está utilizando el cliente HTTP incorporado de Java (vea el espacio de nombre 'sun.net.http' de la propiedad) y espero que funcione en todas las implementaciones de Java, aunque no me es útil ya que Estoy usando el cliente HTTP de Apache's commons. – Guss

Cuestiones relacionadas