2009-09-20 18 views
5

¿Cómo puedo configurar un encabezado de host personalizado en HttpWebRequest? Sé que normalmente esta clase no te permite hacerlo, pero ¿hay alguna forma de utilizar el reflejo o algo así sin que realmente necesite que envíe todo el paquete con TCPClient?¿Cómo establecer el encabezado "Host" personalizado en HttpWebRequest?

+0

¿Qué es exactamente lo que quiere cambiar en el encabezado? Debido a que la mayoría de los parámetros del encabezado pueden ser modificados indirectamente por las propiedades –

+0

¿Por qué necesita configurar el encabezado "Host" usted mismo? Si realiza una solicitud a 'www.google.com', simplemente se convierte en encabezado de host. –

+0

@Yannick Host y otros parámetros reservados no pueden. –

Respuesta

4

Hay una manera indirecta de hacer esto, como se describe aquí:

http://blogs.msdn.com/feroze_daud/archive/2005/03/31/404328.aspx

Sin embargo, la próxima versión del marco (.NET Framework 4.0) hará que sea más fácil.

http://blogs.msdn.com/ncl/archive/2009/07/20/new-ncl-features-in-net-4-0-beta-2.aspx

Espero que esto ayude.

+0

He visto esa página aunque hay muchos problemas en esa solución además de que es una solución muy sucia :) –

+2

Lástima que no utilizo .NET 4 que se ve bien. –

1

Puede utilizar este truco, diseñado para resolver este problema en .Net 3.5.

using System; 
using System.Collections.Generic; 
using System.IO; 
using System.Net; 
using System.Reflection; 


namespace ConsoleApplication6 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create("http://198.252.206.16"); 

      FieldInfo headersFieldInfo = request.GetType().GetField("_HttpRequestHeaders", System.Reflection.BindingFlags.NonPublic 
                | System.Reflection.BindingFlags.Instance 
                | System.Reflection.BindingFlags.GetField); 

      CusteredHeaderCollection WssHeaders = new CusteredHeaderCollection("stackoverflow.com"); 

      headersFieldInfo.SetValue(request, WssHeaders); 

      request.Proxy = null; 
      HttpWebResponse response = (HttpWebResponse)request.GetResponse(); 

      StreamReader sr = new StreamReader(response.GetResponseStream()); 
      string result = sr.ReadToEnd(); 
      Console.WriteLine(result); 
      Console.ReadLine(); 

     } 
     public class CusteredHeaderCollection : WebHeaderCollection 
     { 
      public bool HostHeaderValueReplaced { get;private set; } 

      public string ClusterUrl { get; private set; } 

      public CusteredHeaderCollection(string commonClusterUrl) : base() 
      { 
       if (string.IsNullOrEmpty("commonClusterUrl")) 
        throw new ArgumentNullException("commonClusterUrl"); 

       this.ClusterUrl = commonClusterUrl; 
      } 

      public override string ToString() 
      { 
       this["Host"] = this.ClusterUrl; 
       string tmp = base.ToString(); 
       this.HostHeaderValueReplaced = true; 

       return tmp; 
      } 

     } 
    } 
} 
0

WebClient lo lo permite.

var client = new WebClient(); 
client.Headers.Add("Host", WebHeader); 

No podría decirte por qué. La documentación establece claramente que Host es un encabezado del sistema.

+0

Eso es porque no funciona: el encabezado del host de excepción no se puede cambiar directamente. –

+0

Funciona. Lo estoy usando, en producción – Patrick

+0

No funciona. ArgumentException: este encabezado se debe modificar con la propiedad adecuada. – Mikhail

3

Nigromanciación.
Para aquellos que todavía están en .NET 2.0
De hecho, es bastante fácil, si sabes cómo hacerlo.

El problema es que no puede establecer el encabezado de host porque el marco no le permitirá cambiar el valor en tiempo de ejecución. (.net framework 4.0+ le permitirá anular el host en una httpwebrequest).

El siguiente intento establecerá el encabezado con reflexión, para evitarlo, lo que le permitirá cambiar el valor del encabezado. Pero en tiempo de ejecución, sobrescribirá este valor con la parte del host de la url, lo que significa que la reflexión no le aportará nada.

Si el nombre-dns no existe, lo que es francamente el único caso en el que desea hacer esto en primer lugar, no puede establecerlo, porque .NET no puede resolverlo, y no puede anular la resolución de DNS de .NET.

Pero lo que puede hacer es configurar un servidor web con la misma IP exacta que el servidor de destino.

tanto, si su IP del servidor es 28.14.88.71:

public class myweb : System.Net.WebClient 
{ 
    protected override System.Net.WebRequest GetWebRequest(System.Uri address) 
    { 
     System.Net.WebRequest request = (System.Net.WebRequest)base.GetWebRequest(address); 
     //string host = "redmine.nonexistantdomain.com"; 

     //request.Headers.GetType().InvokeMember("ChangeInternal", 
     // System.Reflection.BindingFlags.NonPublic | 
     // System.Reflection.BindingFlags.Instance | 
     // System.Reflection.BindingFlags.InvokeMethod, null, 
     // request.Headers, new object[] { "Host", host } 
     //); 

     //server IP and port 
     request.Proxy = new System.Net.WebProxy("http://28.14.88.71:80"); 

     // .NET 4.0 only 
     System.Net.HttpWebRequest foo = (System.Net.HttpWebRequest)request; 
     //foo.Host = host; 

     // The below reflection-based operation is not necessary, 
     // if the server speaks HTTP 1.1 correctly 
     // and the firewall doesn't interfere 
     // https://yoursunny.com/t/2009/HttpWebRequest-IP/ 
     System.Reflection.FieldInfo horribleProxyServicePoint = (typeof(System.Net.ServicePoint)) 
      .GetField("m_ProxyServicePoint", System.Reflection.BindingFlags.NonPublic | 
      System.Reflection.BindingFlags.Instance); 

     horribleProxyServicePoint.SetValue(foo.ServicePoint, false); 
     return foo; 



     return request; 
    } 


    } 

y listo, ahora

myweb wc = new myweb(); 
string str = wc.DownloadString("http://redmine.non-existant-domain.com"); 

y se obtiene la página correcta hacia atrás, si 28.14.88.71 es un servidor web con Virtual hosting basado en nombre (basado en http-host-header).

+0

Bueno, para .NET 2.0. Obviamente, esto no funcionará si realmente necesita usar un servidor proxy;) Simplemente actualice a .NET 4.5 ya - WebRequest y WebClient están ambos obsoletos. – User1

Cuestiones relacionadas