Click here to Skip to main content
Click here to Skip to main content
Go to top

Compress Response and HTML WhiteSpace Remover

, 26 Jul 2009
Rate this:
Please Sign up or sign in to vote.
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:

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:

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:

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, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Abhishek Sur
Architect
India India
Did you like his post?
 
Oh, lets go a bit further to know him better.
Visit his Website : www.abhisheksur.com to know more about Abhishek.
 
Abhishek also authored a book on .NET 4.5 Features and recommends you to read it, you will learn a lot from it.
http://bit.ly/EXPERTCookBook
 
Basically he is from India, who loves to explore the .NET world. He loves to code and in his leisure you always find him talking about technical stuffs.
 
Presently he is working in WPF, a new foundation to UI development, but mostly he likes to work on architecture and business classes. ASP.NET is one of his strength as well.
Have any problem? Write to him in his Forum.
 
You can also mail him directly to abhi2434@yahoo.com
 
Want a Coder like him for your project?
Drop him a mail to contact@abhisheksur.com
 
Visit His Blog

Dotnet Tricks and Tips



Dont forget to vote or share your comments about his Writing
Follow on   Twitter   Google+

Comments and Discussions

 
GeneralMy vote of 4 Pinmemberjfriedman15-Mar-12 1:46 
QuestionJavascript error with CDATA tag [modified] Pinmemberhungud10-Feb-12 18:28 
GeneralSomehow Javascript not working Pinmembershaikhsamir28-Jul-10 23:22 
QuestionIs this Reduce Response Header Size?? Pinmembershaikhsamir28-Jul-10 22:49 
GeneralQuestion PinmemberGuzz23-Feb-10 1:57 
QuestionDoes it really strips down whitespaces? Pinmemberranjan_namitaputra2-Oct-09 11:23 
AnswerRe: Does it really strips down whitespaces? PinmemberAbhishek Sur5-Nov-09 21:06 
GeneralMy Vote of 5 Pinmemberalbert_cook11-Aug-09 21:16 
GeneralRe: My Vote of 5 PinmemberAbhishek Sur11-Aug-09 22:15 
QuestionHow About a Little More efficient Example using your code ;) PinmemberMember 460136511-Aug-09 7:44 
AnswerRe: How About a Little More efficient Example using your code ;) PinmemberAbhishek Sur11-Aug-09 22:15 
GeneralRe: How About a Little More efficient Example using your code ;) PinmemberJoão Rollo de Sá11-Aug-09 23:57 
GeneralRe: How About a Little More efficient Example using your code ;) PinmemberAbhishek Sur12-Aug-09 2:08 
GeneralExample request PinmemberPawel7535-Aug-09 23:22 
GeneralRe: Example request PinmemberAbhishek Sur11-Aug-09 22:16 
GeneralRe: Example request PinmemberMohammed Aziz Elnahrawi28-May-10 23:37 
GeneralWhat' a about user serving speed PinmemberHristo Bojilov27-Jul-09 22:41 
GeneralRe: What' a about user serving speed PinmemberAbhishek Sur28-Jul-09 22:19 
GeneralRe: What' a about user serving speed PinmemberAndre Luiz V Sanches13-Aug-09 12:29 
GeneralPlease send me an example. PinmemberlisekR27-Jul-09 4:48 
GeneralRe: Please send me an example. PinmemberAbhishek Sur27-Jul-09 12:45 
GeneralCool Buddy PinmvpAbhijit Jana26-Jul-09 13:24 
GeneralRe: Cool Buddy PinmemberAbhishek Sur26-Jul-09 21:44 
GeneralNice just a few questions Pinmemberspoodygoon26-Jul-09 6:36 
GeneralRe: Nice just a few questions PinmemberAbhishek Sur26-Jul-09 9:14 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web02 | 2.8.140926.1 | Last Updated 27 Jul 2009
Article Copyright 2009 by Abhishek Sur
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid