.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?
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) lo hará 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.
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).
puede usar el proxy, vea mi respuesta en: Solicitar página web en c # falsificando el host