2009-09-20 6 views
5

Come posso impostare un'intestazione Host personalizzata in HttpWebRequest? So che normalmente questa classe non ti permette di farlo, ma c'è comunque un modo per usare il reflection o qualcosa del genere senza che in realtà io abbia bisogno di inviare l'intero pacchetto con TCPClient?Come impostare l'intestazione "Host" personalizzata in HttpWebRequest?

+0

Che cosa si desidera modificare nell'intestazione? Poiché la maggior parte dei parametri dell'intestazione può essere modificata indirettamente dalle proprietà –

+0

Perché è necessario impostare da soli l'intestazione "Host". Se fai una richiesta a 'www.google.com', diventa semplicemente intestazione host. –

+0

@Yannick Host e altri parametri riservati non possono. –

risposta

4

C'è un modo indiretto per fare questo, come descritto qui:

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

Tuttavia, la prossima versione del framework (.NET Framework 4.0) renderà più facile.

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

Spero che questo aiuti.

+0

Ho visto quella pagina anche se ci sono molti problemi in questa soluzione alternativa a parte ciò è una soluzione veramente sporca :) –

+2

Shame Non uso .NET 4 che sembra buono. –

1

È possibile utilizzare questo hack, progettato per risolvere questo problema in .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 consente.

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

Non saprei dire perché. La documentazione indica chiaramente che Host è un'intestazione di sistema.

+0

Questo perché non funziona: l'intestazione dell'host di eccezione non può essere modificata direttamente. –

+0

Funziona. Lo sto utilizzando, in produzione – Patrick

+0

Non funziona. ArgumentException: questa intestazione deve essere modificata con la proprietà appropriata. – Mikhail

3

Negromante.
Per quelli ancora su .NET 2.0
In effetti è abbastanza semplice, se si sa come.

Il problema è che non è possibile impostare l'intestazione host, poiché il framework non consente di modificare il valore in fase di esecuzione. (.net framework 4.0+ consente di eseguire l'override dell'host in una httpwebrequest).

Il prossimo tentativo sarà l'impostazione dell'intestazione con riflessione, per aggirare il problema, che ti consentirà di modificare il valore dell'intestazione. Ma al momento dell'esecuzione, sovrascrive questo valore con la parte host dell'URL, il che significa che la riflessione non ti porterà nulla.

Se il nome dns non esiste, che è francamente l'unico caso in cui si desidera eseguire ciò in primo luogo, non è possibile impostarlo, perché .NET non può risolverlo e non è possibile ignorare il risolutore DNS .NET.

Ma quello che puoi fare è impostare un webproxy con lo stesso IP del server di destinazione.

Quindi, se il vostro IP del server è 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; 
    } 


    } 

e voilà, ora

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

e si ottiene la pagina corretta indietro, se 28.14.88.71 è un web server con Virtual hosting basato sul nome (basato su http-host-header).

+0

Nice, per .NET 2.0. Ovviamente, questo non funzionerà se si ha effettivamente bisogno di usare un server proxy;) Basta aggiornare a .NET 4.5 già - WebRequest e WebClient sono entrambi deprecati comunque. – User1