Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Compress Response and HTML WhiteSpace Remover

0.00/5 (No votes)
26 Jul 2009 1  
Use of GZipStream or DeflateStream to compress your HTML output in your response when available. Added new class as WhiteSpaceFilter to remove whitespaces from HTML.

Compression

It is obvious that we need to compress our response while passing it to the client. Compressed requests and responses always increase the performance of sites. Nowadays, almost 99 percent of browsers support either Gzip or Deflate compression or both. So, if we can check if the accept-encoding header is present and return a compressed response to the client, then we have just improved our site performance. Just take a look at the code below:

C#
public static void doCompression()
{
     HttpContext context = HttpContext.Current;
     HttpRequest request = context.Request;
     string acceptEncoding = request.Headers["Accept-Encoding"];
     HttpResponse response = context.Response;
     if (!string.IsNullOrEmpty(acceptEncoding))
     {
         acceptEncoding = acceptEncoding.ToUpperInvariant();
         if (acceptEncoding.Contains("GZIP"))
         {
             response.Filter = new GZipStream(context.Response.Filter, 
             CompressionMode.Compress);
             response.AppendHeader("Content-encoding", "gzip");
         }
         else if (acceptEncoding.Contains("DEFLATE"))
         {
             response.Filter = new DeflateStream(context.Response.Filter, 
             CompressionMode.Compress);
             response.AppendHeader("Content-encoding", "deflate");
         }
     }
     response.Cache.VaryByHeaders["Accept-Encoding"] = true;
}

Here, we are checking if the Request header contains [“Accept-Encoding”]. Based on the encoding it supports, we filter the response using GZipStream/ DeflateStream which are available in the System.IO.Compression namespace. Thus the response will be compressed. Only, this will not help the client to render your page properly. You need to add the Content-Encoding header to the response, so it can decompress the response in the client properly. We add a Response header “Accept-Encoding” so that the request is also made using the same encoding it is sending the data in.

You can also remove whitespaces from your HTML to shrink the response. Use this class:

C#
public enum CompressOptions
{
    GZip,
    Deflate,
    None
}

public class WhitespaceFilter : Stream
{
    private GZipStream _contentGZip;
    private DeflateStream _content_Deflate;
    private Stream _content;
    private CompressOptions _options;

    public WhitespaceFilter(Stream content, CompressOptions options)
    {
        if (options == CompressOptions.GZip)
        {
            this._contentGZip = new GZipStream(content, CompressionMode.Compress);
            this._content = this._contentGZip;
        }
        else if (options == CompressOptions.Deflate)
        {
            this._content_Deflate = new DeflateStream(content, 
                  CompressionMode.Compress);
            this._content = this._content_Deflate;
        }
        else
        {
            this._content = content;
        }
        this._options = options;
    }


    public override bool CanRead
    {
        get { return this._content.CanRead; }
    }

    public override bool CanSeek
    {
        get { return this._content.CanSeek; }
    }

    public override bool CanWrite
    {
        get { return this._content.CanWrite; }
    }

    public override void Flush()
    {
        this._content.Flush();
    }

    public override long Length
    {
        get { return this._content.Length; }
    }

    public override long Position
    {
        get
        {
            return this._content.Position;
        }
        set
        {
            this._content.Position = value;
        }
    }

    public override int Read(byte[] buffer, int offset, int count)
    {
        return this._content.Read(buffer, offset, count);
    }

    public override long Seek(long offset, SeekOrigin origin)
    {
        return this._content.Seek(offset, origin);
    }

    public override void SetLength(long value)
    {
        this._content.SetLength(value);
    }

    public override void Write(byte[] buffer, int offset, int count)
    {
        byte[] data = new byte[count + 1];
        Buffer.BlockCopy(buffer, offset, data, 0, count);

        string s = System.Text.Encoding.UTF8.GetString(data);
        s = Regex.Replace(s, "^\\s*",string.Empty, RegexOptions.Compiled |
                          RegexOptions.Multiline);
        s = Regex.Replace(s, "\\r\\n", string.Empty, RegexOptions.Compiled | 
                          RegexOptions.Multiline);
        s = Regex.Replace(s, "<!--*.*?-->", string.Empty, RegexOptions.Compiled | 
                          RegexOptions.Multiline); 
        
        byte[] outdata = System.Text.Encoding.UTF8.GetBytes(s);
        this._content.Write(outdata, 0, outdata.GetLength(0));
    }
}

To use it, just write:

C#
internal void Compress()
{
    HttpContext context = HttpContext.Current;
    HttpRequest request = context.Request;
    string acceptEncoding = request.Headers["Accept-Encoding"];
    HttpResponse response = context.Response;
    if (!string.IsNullOrEmpty(acceptEncoding))
    {
        acceptEncoding = acceptEncoding.ToUpperInvariant();
        if (acceptEncoding.Contains("GZIP"))
        {
            //response.Filter = new GZipStream(context.Response.Filter, 
                                //CompressionMode.Compress);
            response.Filter = new WhitespaceFilter(context.Response.Filter, 
                              CompressOptions.GZip);
            response.AppendHeader("Content-encoding", "gzip");
        }
        else if (acceptEncoding.Contains("DEFLATE"))
        {
            //response.Filter = new DeflateStream(context.Response.Filter, 
                                //CompressionMode.Compress);
            response.Filter = new WhitespaceFilter(context.Response.Filter, 
                              CompressOptions.Deflate);
            response.AppendHeader("Content-encoding", "deflate");
        }
    }
    response.Cache.VaryByHeaders["Accept-Encoding"] = true;
}

Note: The Regular Expressions that I have used will remove extra spaces, newlines, and comments from the HTML. Thus, it will reduce the size of the HTML. Also, before using it in production, check how it is working, because you need to change the Regular Expressions according to your needs.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here