8

How can I set a custom Host header in HttpWebRequest? I know that normally this class doesn't allow you to do so but is there anyway to use reflection or something like that without actually need me to send the whole packet with TCPClient?

3
  • What exactly do you want to change in the header? Because most of the header parameters can be indirectly modified by properties Commented Sep 20, 2009 at 12:46
  • Why do you need to set "Host" header by yourself. If you make request to www.google.com, it simply becomes host header. Commented Sep 20, 2009 at 12:54
  • @Yannick Host and other reserved parameters can't. Commented Sep 20, 2009 at 17:36

5 Answers 5

6

There is a roundabout way to do this, as described here:

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

However, the next version of the framework (.NET Framework 4.0) will make it easier.

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

Hope this helps.

Sign up to request clarification or add additional context in comments.

1 Comment

I've seen that page although there are lots of problems in that workaround beside of that it's a really dirty workaround :)
3

Necromancing.
For those still on .NET 2.0
It is in fact quite easy, if you know how.

Problem is, you can't set the host header, because the framework won't let you change the value at runtime. (.net framework 4.0+ will let you override host in a httpwebrequest).

Next attempt will be setting the header with reflection, to get around it, which will let you change the header value. But at runtime, it will overwrite this value with the host part of the url, which means reflection will bring you nothing.

If the dns-name doesn't exist, which is quite frankly the only case in which you want to do this in the first place, you can't set it, because .NET can't resolve it, and you can't override the .NET DNS resolver.

But what you can do, is setting a webproxy with the exact same IP as the destination server.

So, if your server IP is 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;
    }


    }

and voila, now

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

and you get the correct page back, if 28.14.88.71 is a webserver with virtual name-based hosting (based on http-host-header).

1 Comment

Nice, for .NET 2.0. Obviously, this won't work if you actually need to use a proxy-server ;) Just upgrade to .NET 4.5 already - WebRequest and WebClient are both deprecated anyway.
3

You can use this hack, designed for solve this problem 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);

            ClusteredHeaderCollection headers = new ClusteredHeaderCollection("stackoverflow.com");

            headersFieldInfo.SetValue(request, headers);

            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 ClusteredHeaderCollection : WebHeaderCollection
        {
            public bool HostHeaderValueReplaced { get;private  set; }

            public string ClusterUrl { get; private set; }

            public ClusteredHeaderCollection(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;
            }
        }
    }
}

Comments

1

WebClient allows it.

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

I couldn't tell you why. The documentation clearly states that Host is a system header.

3 Comments

That's because it doesn't work - exception host header cannot be directly changed.
Not works. ArgumentException: This header must be modified with the appropiate property.
It literally works. As I said, running in production. System.Net.WebClient. Target 3.5
0

you can use proxy, see my answer at: Request Web Page in c# spoofing the Host

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.