2009-09-20 3 views
5

Как настроить собственный заголовок узла в HttpWebRequest? Я знаю, что обычно этот класс не позволяет вам это делать, но все равно использовать рефлексию или что-то в этом духе, не нужно ли мне отправлять весь пакет с помощью TCPClient?Как настроить пользовательский заголовок «Host» в HttpWebRequest?

+0

Что именно вы хотите изменить в заголовке? Поскольку большинство параметров заголовка могут быть косвенно изменены свойствами –

+0

Зачем вам нужно устанавливать заголовок «Host» самостоятельно. Если вы делаете запрос на «www.google.com», он просто становится заголовком хоста. –

+0

@ Yannick Host и другие зарезервированные параметры не могут. –

ответ

4

Существует обходной путь, чтобы сделать это, как описано здесь:

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

Однако следующая версия базы (.NET Framework 4.0) будет проще.

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

Надеется, что это помогает.

+0

Я видел эту страницу, хотя в этом обходном пути есть много проблем, потому что это действительно грязный обходной путь :) –

+2

Позор Я не использую .NET 4, который выглядит хорошо. –

1

Вы можете использовать этот хак, предназначенный для решения этой проблемы в .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 позволяет это использовать.

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

Я не мог сказать, почему. В документации четко указано, что Host является системным заголовком.

+0

Это потому, что он не работает - заголовок узла исключения не может быть напрямую изменен. –

+0

Работает. Я использую его, в производстве – Patrick

+0

Не работает. ArgumentException: этот заголовок должен быть изменен с помощью свойства appropiate. – Mikhail

3

Некронирование.
Для тех, кто еще на .NET 2.0
На самом деле это довольно просто, если вы знаете, как это сделать.

Проблема в том, что вы не можете установить заголовок хоста, потому что фреймворк не позволит вам изменить значение во время выполнения. (.net framework 4.0+ позволит вам переопределить хост в httpwebrequest).

Следующая попытка будет включать заголовок с отражением, чтобы обойти его, что позволит вам изменить значение заголовка. Но во время выполнения он перезапишет это значение хост-частью URL-адреса, что означает, что отражение ничего не принесет вам.

Если имя dns не существует, что, откровенно говоря, является единственным случаем, в котором вы хотите сделать это в первую очередь, вы не можете установить его, потому что .NET не может его решить, и вы не можете переопределить .NET DNS-резольвер.

Но что вы можете сделать, настраивает веб-прокси с тем же IP-адресом, что и целевой сервер.

Таким образом, если ваш IP сервер 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; 
    } 


    } 

и вуаля, теперь

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

и вы получите нужную страницу назад, если 28.14.88.71 является веб-сервер с виртуальным основанный на имени хостинг (на основе http-host-header).

+0

Nice, для .NET 2.0. Очевидно, что это не сработает, если вам действительно нужно использовать прокси-сервер;) Просто обновите до .NET 4.5 уже - WebRequest и WebClient обе устали в любом случае. – User1

Смежные вопросы