Wie kann ich einen benutzerdefinierten Host-Header in HttpWebRequest festlegen? Ich weiß, dass normalerweise diese Klasse das nicht erlaubt, aber gibt es trotzdem Reflektionen oder ähnliches, ohne dass ich das ganze Paket mit TCPClient senden muss?Wie benutzerdefinierte Header "Host" in HttpWebRequest festlegen?
Antwort
Es gibt einen Kreisverkehr Weg, dies zu tun, wie hier beschrieben:
http://blogs.msdn.com/feroze_daud/archive/2005/03/31/404328.aspx
jedoch die nächste Version des Frameworks (.NET Framework 4.0) wird es leichter.
http://blogs.msdn.com/ncl/archive/2009/07/20/new-ncl-features-in-net-4-0-beta-2.aspx
Hoffnung, das hilft.
Ich habe diese Seite gesehen, obwohl es viele Probleme in dieser Problemumgehung gibt, abgesehen davon, dass es eine wirklich dreckige Workaround ist :) –
Schade, dass ich .NET 4 nicht benutze, das gut aussieht. –
können Sie Proxy verwenden, siehe meine Antwort auf: Request Web Page in c# spoofing the Host
können Sie diesen Hack verwenden, die für dieses Problem in .NET 3.5 zu lösen.
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;
}
}
}
}
WebClient ermöglicht es.
var client = new WebClient();
client.Headers.Add("Host", WebHeader);
Ich konnte Ihnen nicht sagen warum. Die Dokumentation besagt eindeutig, dass Host ein Systemkopf ist.
Necromancing.
Für diejenigen, die immer noch auf .NET 2.0
Es ist in der Tat ziemlich einfach, wenn Sie wissen, wie.
Problem ist, dass Sie den Host-Header nicht festlegen können, da das Framework den Wert nicht zur Laufzeit ändern kann. (.net Framework 4.0 + lässt Sie Host in einer httpwebrequest überschreiben).
Nächster Versuch wird die Überschrift mit Reflexion setzen, um es zu umgehen, mit dem Sie den Header-Wert ändern können. Aber zur Laufzeit überschreibt es diesen Wert mit dem Host-Teil der URL, was bedeutet, dass Reflektion nichts bringt.
Wenn der DNS-Name nicht existiert, was ehrlich gesagt der einzige Fall ist, in dem Sie dies überhaupt tun wollen, können Sie es nicht setzen, weil .NET es nicht auflösen kann, und Sie können den .NET DNS-Resolver nicht überschreiben.
Aber was Sie tun können, ist ein Webproxy mit der gleichen IP wie der Zielserver einstellen.
Also, wenn Ihr Server-IP ist 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;
}
}
und voila, jetzt
myweb wc = new myweb();
string str = wc.DownloadString("http://redmine.non-existant-domain.com");
und Sie die richtige Seite zurück, wenn 28.14.88.71 ein Webserver mit virtuell Namensbasiertes Hosting (basierend auf http-Host-Header).
Schön, für .NET 2.0. Offensichtlich funktioniert das nicht, wenn Sie tatsächlich einen Proxy-Server benutzen müssen.) Aktualisieren Sie einfach auf .NET 4.5 - WebRequest und WebClient sind sowieso veraltet. – User1
Was genau möchten Sie in der Kopfzeile ändern? Da die meisten Header-Parameter indirekt durch die Eigenschaften –
geändert werden können, müssen Sie den Header "Host" selbst festlegen. Wenn Sie eine Anfrage an "www.google.com" senden, wird diese einfach zum Host-Header. –
@ Yannick Host und andere reservierte Parameter können nicht. –