Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

HttpModule to add headers to request

This seems like a simple operation.

We have a need in our development environment (running on XP/IIS 5) to add some headers into each HttpRequest arriving at our application. (This is to simulate a production environment that we don't have available in dev). At first blush, this seemed like a simple HttpModule, along the lines of:

public class Dev_Sim: IHttpModule
{
    public void Init(HttpApplication app)
    {
        app.BeginRequest += delegate { app.Context.Request.Headers.Add("UserName", "XYZZY"); };
    }

    public void Dispose(){}
}

But on trying to do that, I find that the Headers collection of the Request is read-only, and the Add method fails with an OperationNotSupported exception.

Spending a couple hours researching this on Google, I've come up with no easy answer to what should be a relatively straight-forward problem.

Does anyone have any pointers?

like image 363
Dave Hanna Avatar asked Nov 03 '10 20:11

Dave Hanna


1 Answers

Okay, with the assistance of a co-worker and some experimentation, I found that this can be done with the assistance of some protected properties and methods accessed through reflection:

var headers = app.Context.Request.Headers;
Type hdr = headers.GetType();
PropertyInfo ro = hdr.GetProperty("IsReadOnly", 
    BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.IgnoreCase | BindingFlags.FlattenHierarchy);
// Remove the ReadOnly property
ro.SetValue(headers, false, null);
// Invoke the protected InvalidateCachedArrays method 
hdr.InvokeMember("InvalidateCachedArrays", 
    BindingFlags.InvokeMethod | BindingFlags.NonPublic | BindingFlags.Instance, 
    null, headers, null);
// Now invoke the protected "BaseAdd" method of the base class to add the
// headers you need. The header content needs to be an ArrayList or the
// the web application will choke on it.
hdr.InvokeMember("BaseAdd", 
    BindingFlags.InvokeMethod | BindingFlags.NonPublic | BindingFlags.Instance, 
    null, headers, 
    new object[] { "CustomHeaderKey", new ArrayList {"CustomHeaderContent"}} );
// repeat BaseAdd invocation for any other headers to be added
// Then set the collection back to ReadOnly
ro.SetValue(headers, true, null);

This works for me, at least.

like image 62
Dave Hanna Avatar answered Oct 05 '22 10:10

Dave Hanna