Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Looking for a HTTPHandler to modify pages on the fly to point to a CDN

What I'm trying to do is create (or perhaps one already exists) a HTTPHandler that will filter the HTML generated ASP.NET to use the content delivery network (CDN). For example, I want to rewrite references such as this:

/Portals/_default/default.css

to

http://cdn.example.com/Portals/_default/default.css

I'm perfectly happy using RegEx to match the initial strings. Such a regex patterns might be:

href=['"](/Portals/.+\.css)

or

src=['"](/Portals/.+\.(css|gif|jpg|jpeg))

This is a dotnetnuke site and I don't really have control over all the HTML generated so that's why I want to do it with an HTTPHandler. That way the changes can be done post-page generation.

like image 636
Keltex Avatar asked May 19 '11 15:05

Keltex


1 Answers

You could write a response filter which can be registered in a custom HTTP module and which will modify the generated HTML of all pages running the regex you showed.

For example:

public class CdnFilter : MemoryStream
{
    private readonly Stream _outputStream;
    public CdnFilter(Stream outputStream)
    {
        _outputStream = outputStream;
    }

    public override void Write(byte[] buffer, int offset, int count)
    {
        var contentInBuffer = Encoding.UTF8.GetString(buffer);

        contentInBuffer = Regex.Replace(
            contentInBuffer, 
            @"href=(['""])(/Portals/.+\.css)",
            m => string.Format("href={0}http://cdn.example.com{1}", m.Groups[1].Value, m.Groups[2].Value)
        );

        contentInBuffer = Regex.Replace(
            contentInBuffer,
            @"src=(['""])(/Portals/.+\.(css|gif|jpg|jpeg))",
            m => string.Format("href={0}http://cdn.example.com{1}", m.Groups[1].Value, m.Groups[2].Value)
        );

        _outputStream.Write(Encoding.UTF8.GetBytes(contentInBuffer), offset, Encoding.UTF8.GetByteCount(contentInBuffer));
    }
}

and then write a module:

public class CdnModule : IHttpModule
{
    void IHttpModule.Dispose()
    {
    }

    void IHttpModule.Init(HttpApplication context)
    {
        context.ReleaseRequestState += new EventHandler(context_ReleaseRequestState);
    }

    void context_ReleaseRequestState(object sender, EventArgs e)
    {
        HttpContext.Current.Response.Filter = new CdnFilter(HttpContext.Current.Response.Filter);
    }
}

and register in web.config:

<httpModules>
  <add name="CdnModule" type="MyApp.CdnModule, MyApp"/>
</httpModules>
like image 173
Darin Dimitrov Avatar answered Sep 23 '22 03:09

Darin Dimitrov