With .NET 2.0 we are given System.IO.Compression that allows us to easily implement HTTPCompression on a per-application basis and if we want to get creative with our C#, we can customize it even more!
If you take a look here you will see a tutorial on how you can get this up and working. Once you implement this, it works great, almost...
Once you follow all of their instructions and run a few tests you will find that your pages are now using HTTPCompression saving you mucho bandwidth as well as making large downloads much faster for your users! HOWEVER, you will also notice that images begin to break and occassionally IE will crash! All is not well!
As I'm sure many of you know, IE (and I believe some versions of Mozilla-based browsers though I could be wrong) have a/some bug(s) in them that causes them to not properly handle images and other things (PDFs don't get properly passed to Adobe, etc.) when they are compressed with HTTPCompression.
I've taken the above-linked demo and modified the logic to allow you to control what does and does not get compressed. I basically take the URI being requested and do a search for ".htm" or ".aspx" and if I find it, I compress the response, otherwise I leave it alone. This is not a fool-proof system as it would compress foo.htm.jpg even though it's an image and it would not (at least I don't think it would) compress "http://www.domain.com/" as the actual URI being requested doesn't specify the actual page so these two things should be kept in mind as "loopholes" in my system but it's good enough for me. :)
Here's the code:
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Text;
using System.Web;
namespace MSDN.Demo.Whidbey.Compression
{
public class HttpCompressionModule : IHttpModule
{
public HttpCompressionModule()
{
}
void IHttpModule.Dispose()
{
}
void IHttpModule.Init(HttpApplication context)
{
context.BeginRequest += new EventHandler(context_BeginRequest);
}
void context_BeginRequest(object sender, EventArgs e)
{
//
// Get the application object to gain access to the request's details
//
HttpApplication app = (HttpApplication)sender;
//
// Accepted encodings
//
string encodings = app.Request.Headers.Get("Accept-Encoding");
//
// No encodings; stop the HTTP Module processing
//
if (encodings == null)
return;
if (ShouldCompress(app.Request.Url.ToString()))
{
//
// Current response stream
//
Stream baseStream = app.Response.Filter;
//
// Find out the requested encoding
//
encodings = encodings.ToLower();
if (encodings.Contains( "gzip" ))
{
app.Response.Filter = new GZipStream( baseStream, CompressionMode.Compress );
app.Response.AppendHeader( "Content-Encoding", "gzip" );
#if DEBUG
app.Context.Trace.Warn( "GZIP compression on" );
#endif
}
else if (encodings.Contains( "deflate" ))
{
app.Response.Filter = new DeflateStream( baseStream, CompressionMode.Compress );
app.Response.AppendHeader( "Content-Encoding", "deflate" );
#if DEBUG
app.Context.Trace.Warn( "Deflate compression on" );
#endif
}
}
}
private bool ShouldCompress( string s )
{
string str = s.ToLower();
if ((str.Contains( ".aspx" )) || (str.Contains( ".htm" )))
{
return true;
}
else
{
return false;
}
}
}
}
Enjoy!