2009-09-20 13 views
5

Jak ustawić niestandardowy nagłówek hosta w HttpWebRequest? Wiem, że normalnie ta klasa nie pozwala ci na to, ale czy mimo to używasz odbicia lub czegoś podobnego bez potrzeby wysyłania całego pakietu za pomocą TCPClient?Jak ustawić niestandardowy nagłówek "Host" w HttpWebRequest?

+0

Co dokładnie chcesz zmienić w nagłówku? Ponieważ większość parametrów nagłówka może być pośrednio modyfikowana przez właściwości –

+0

. Dlaczego musisz ustawić nagłówek "Host" samodzielnie. Jeśli poprosisz o "www.google.com", stanie się on po prostu nagłówkiem hosta. –

+0

@Nickick Host i inne zastrzeżone parametry nie mogą. –

Odpowiedz

4

Jest rondo sposobem, aby to zrobić, jak to opisano tutaj:

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

Jednak kolejna wersja ram (.NET Framework 4.0) będzie łatwiej.

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

Nadzieja to pomaga.

+0

Widziałem tę stronę, chociaż istnieje wiele problemów w tym obejściu, oprócz tego, że jest to naprawdę brudne obejście :) –

+2

Wstyd Nie używam .NET 4, który wygląda dobrze. –

1

Można użyć tego hack, przeznaczonego dla rozwiązania tego problemu w .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 na to pozwala.

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

Nie mogłem ci powiedzieć dlaczego. Dokumentacja wyraźnie stwierdza, że ​​Host jest nagłówkiem systemu.

+0

To dlatego, że nie działa - nagłówek hosta wyjątku nie może być bezpośrednio zmieniony. –

+0

To działa. Używam go w produkcji – Patrick

+0

Nie działa. ArgumentException: Ten nagłówek musi zostać zmodyfikowany za pomocą odpowiedniej właściwości. – Mikhail

3

Nekromowanie.
Dla tych, którzy wciąż na .NET 2.0
Jest to w rzeczywistości dość łatwe, jeśli wiesz jak.

Problem polega na tym, że nie można ustawić nagłówka hosta, ponieważ struktura nie pozwala na zmianę wartości w czasie wykonywania. (.net framework 4.0+ pozwoli ci przesłonić hosta w httpwebrequest).

Następną próbą będzie ustawienie nagłówka z odbiciem, aby obejść go, co pozwoli ci zmienić wartość nagłówka. Ale w czasie działania nadpisze tę wartość z częścią hosta adresu URL, co oznacza, że ​​refleksja nie przyniesie nic.

Jeśli nazwa dns nie istnieje, co jest szczerym jedynym przypadkiem, w którym chcesz to zrobić w pierwszej kolejności, nie możesz jej ustawić, ponieważ .NET nie może go rozwiązać, i nie można przesłonić resolwera .NET DNS.

Ale możesz ustawić webproxy z tym samym adresem IP co serwer docelowy.

Dlatego, jeśli IP serwera jest 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; 
    } 


    } 

i voila, teraz

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

i masz odpowiednią stronę z powrotem, jeśli 28.14.88.71 jest serwer WWW z wirtualnym hosting oparty na nazwach (oparty na nagłówku hosta http).

+0

Przyjemnie, dla .NET 2.0. Oczywiście to nie zadziała, jeśli rzeczywiście będziesz potrzebować serwera proxy;) Wystarczy dokonać aktualizacji do .NET 4.5 - WebRequest i WebClient są i tak przestarzałe. – User1

Powiązane problemy