It Hurts When I Set the User Agent


Consider the following simple test server that uses no WCF code at all.

using System;
using System.Net;

class Server
{
static void Main(string[] args)
{
HttpListener listener = new HttpListener();
listener.Prefixes.Add("http://localhost:1000/");
listener.Start();
HttpListenerContext context = listener.GetContext();
Console.Out.WriteLine(context.Request.Headers);
context.Response.Close();
listener.Stop();
Console.ReadLine();
}
}

Consider the following simple test client that uses no WCF code at all.

using System;
using System.Net;

class Client
{
static void Main(string[] args)
{
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create("http://localhost:1000");
request.Accept = "*/*";
request.UserAgent = "fooagent";
request.Headers[HttpRequestHeader.MaxForwards] = "10";
Console.Out.WriteLine(request.Headers);
request.GetResponse().Close();
Console.ReadLine();
}
}

A funny thing happens on the way from the client to the server. If you look at the headers collection on the client, it contains all of the headers that we set. If you look at the headers collection on the server, it contains all of the headers that we set except for the user agent header. It turns out that HttpListener will always drop the user agent header (and only that header) from the header collection. Since our self-hosted HTTP transport uses the HttpListener header collection to populate the HTTP headers, that means you’ll never see a user agent header even if a client sets one. You should be fine when running a service hosted in IIS because that has an entirely different mechanism for listening for HTTP requests.

Of course, we’re not entirely free of header foibles of our own. For fun, try setting the Referer header on a WCF client.

Expect these things to just work when WCF is released.

Comments (3)

  1. scott o says:

    Dropped but still available:

    HttpListenerContext context = listener.GetContext ();

    HttpListenerRequest request = context.Request;

    Console.WriteLine ("{0}", request.UserAgent);

  2. Nicholas Allen says:

    That’s what you do if you have access to the request object.  The HTTP transport in WCF uses HttpListener internally but doesn’t make the listener context visible.  You have to wait for the framework to get updated even though the change in the framework is one line.