I'm currently working on a project where we need to integrate with a php app (Revive AdServer
FWIW). Revive has invocation javascript code
you deploy to sites where you'd like to serve ads and when the code
renders on those sites, it calls the php app and intelligently displays
an ad based on the query string passed in. Our task was intercept the call after it's made from one of
those sites and before it hits the php app, and manipulate the query
string so that a different ad is served based on data we have for the current use in our database. We control the server it's deployed to, but altering the php code to do what we need to is not an option.
You can accomplish this problem by writing an HttpModule and then adding it to IIS
on the php app server. Here is the code:
public class AdServerModule : IHttpModule
{
public void OnBeginRequest(object sender, EventArgs e)
{
var context = ((HttpApplication)sender).Context;
var queryString = context.Request.QueryString;
var readonlyProperty = queryString.GetType().GetProperty("IsReadOnly", BindingFlags.Instance | BindingFlags.NonPublic);
readonlyProperty.SetValue(queryString, false, null);
var path = GetVirtualPath(context);
queryString.Add("foo", "bar");
context.RewritePath(path, String.Empty, queryString.ToString());
readonlyProperty.SetValue(queryString, true, null);
}
public void Init(HttpApplication context)
{
context.BeginRequest += new EventHandler(OnBeginRequest);
}
private static string GetVirtualPath(HttpContext context)
{
var path = context.Request.RawUrl;
var queryStringIndex = path.IndexOf("?");
path = path.Substring(0, queryStringIndex >= 0 ? queryStringIndex : path.Length);
path = path.Substring(path.LastIndexOf("/") + 1);
return path;
}
public void Dispose() { }
}
The OnBeginRequest() method fires on the php server before the php app handles the request. As you can see, I'm using reflection to make the QueryString property of the request not read only. You don't necessarily have to do this as long as you pass your intended query string into the RewritePath() call. The RewritePath() call is where request is actually changed. You also aren't just limited to manipulating the URL. The Request object is completely exposed so you can alter the Form, Headers, etc.
Once you've written the HttpModule, you need to deploy it. First you need to register the HttpModule's assembly into the GAC on the machine where you're deploying it (in our case, the php app server) using the following command:
gacutil /i c:\MyHttpModule.dll
Note that if your HttpModule has references that don't exist on the target machine, you'll need to include them in your assembly (ILMerge FTW). You'll also most likely have to sign referenced assemblies that you wrote for the gacutil like so:
Once your assembly is loaded on the target machine, you just need to register that module to IIS. You can do this in the web.config:
<system.webServer>
<modules runAllManagedModulesForAllRequests="true">
<add type="Product.AdServer.TrafficManager.AdServerModule" name="AdServerModule" />
</modules> </system.webServer>
You can also register the module directly in IIS:
That's it!