Как установить собственный заголовок узла в HttpWebRequest?

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


person dr. evil    schedule 20.09.2009    source источник
comment
Что именно вы хотите изменить в шапке? Поскольку большинство параметров заголовка могут быть косвенно изменены свойствами   -  person Yannick Motton    schedule 20.09.2009
comment
Зачем вам нужно устанавливать заголовок Host самостоятельно. Если вы делаете запрос к www.google.com, он просто становится заголовком хоста.   -  person lubos hasko    schedule 20.09.2009
comment
@Yannick Host и другие зарезервированные параметры не могут.   -  person dr. evil    schedule 20.09.2009


Ответы (5)


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

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

Надеюсь это поможет.

person feroze    schedule 20.09.2009
comment
Я видел эту страницу, хотя в этом обходном пути есть много проблем, кроме того, что это действительно грязный обходной путь :) - person dr. evil; 20.09.2009

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

        }
    }
}
person user2225191    schedule 02.09.2013

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

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

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

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

Но что вы можете сделать, так это установить веб-прокси с точно таким же 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).

person Stefan Steiger    schedule 19.12.2016
comment
Отлично, для .NET 2.0. Очевидно, что это не сработает, если вам действительно нужно использовать прокси-сервер;) Просто обновите уже до .NET 4.5 - WebRequest и WebClient в любом случае устарели. - person ; 21.12.2016

WebClient это позволяет.

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

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

person Patrick    schedule 03.05.2016
comment
Это потому, что это не работает - заголовок хоста исключения нельзя изменить напрямую. - person Stefan Steiger; 19.12.2016
comment
Не работает. ArgumentException: этот заголовок должен быть изменен соответствующим свойством. - person Mikhail; 16.05.2017
comment
Это буквально работает. Как я уже сказал, запущен в производство. Система.Net.ВебКлиент. Цель 3.5 - person Patrick; 17.05.2017

вы можете использовать прокси, см. мой ответ по адресу: Request Web Страница в c#, ​​подделывающая хост

person thedrs    schedule 12.12.2010