.net http reflection httpwebrequest host

.net - ¿Cómo establecer el encabezado "Host" personalizado en HttpWebRequest?



reflection (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?



Puede usar 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(".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; } } } }


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


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

El problema es que no puede configurar el encabezado del 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 será configurar el encabezado con reflejo, 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 usted no puede anula la resolución .NET DNS.

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

Entonces, si la IP de su 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 voila, ahora

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

y recupera la página correcta, si 28.14.88.71 es un servidor web con alojamiento virtual basado en nombre (basado en http-host-header).