Click here to Skip to main content
15,921,113 members
Articles / Web Development / XHTML

Compress Response and HTML WhiteSpace Remover

Rate me:
Please Sign up or sign in to vote.
4.85/5 (26 votes)
26 Jul 2009CPOL1 min read 191.6K   50   26
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, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
President
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.

Working as a VP product of APPSeCONNECT, an integration platform of future, he does all sort of innovation around the product.

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

Comments and Discussions

 
QuestionNoob Question Pin
John Vicencio23-May-18 10:16
John Vicencio23-May-18 10:16 
GeneralMy vote of 4 Pin
jfriedman15-Mar-12 1:46
jfriedman15-Mar-12 1:46 
QuestionJavascript error with CDATA tag Pin
hungud10-Feb-12 18:28
hungud10-Feb-12 18:28 
GeneralSomehow Javascript not working Pin
shaikhsamir28-Jul-10 23:22
shaikhsamir28-Jul-10 23:22 
QuestionIs this Reduce Response Header Size?? Pin
shaikhsamir28-Jul-10 22:49
shaikhsamir28-Jul-10 22:49 
GeneralQuestion Pin
Guus Beltman23-Feb-10 1:57
Guus Beltman23-Feb-10 1:57 
QuestionDoes it really strips down whitespaces? Pin
ranjan_namitaputra2-Oct-09 11:23
ranjan_namitaputra2-Oct-09 11:23 
AnswerRe: Does it really strips down whitespaces? Pin
Abhishek Sur5-Nov-09 21:06
professionalAbhishek Sur5-Nov-09 21:06 
GeneralMy Vote of 5 Pin
albert_cook11-Aug-09 21:16
albert_cook11-Aug-09 21:16 
GeneralRe: My Vote of 5 Pin
Abhishek Sur11-Aug-09 22:15
professionalAbhishek Sur11-Aug-09 22:15 
QuestionHow About a Little More efficient Example using your code ;) Pin
João Rollo de Sá11-Aug-09 7:44
João Rollo de Sá11-Aug-09 7:44 
AnswerRe: How About a Little More efficient Example using your code ;) Pin
Abhishek Sur11-Aug-09 22:15
professionalAbhishek Sur11-Aug-09 22:15 
GeneralRe: How About a Little More efficient Example using your code ;) Pin
João Rollo de Sá11-Aug-09 23:57
João Rollo de Sá11-Aug-09 23:57 
GeneralRe: How About a Little More efficient Example using your code ;) Pin
Abhishek Sur12-Aug-09 2:08
professionalAbhishek Sur12-Aug-09 2:08 
GeneralExample request Pin
Pawel Wroc5-Aug-09 23:22
Pawel Wroc5-Aug-09 23:22 
GeneralRe: Example request Pin
Abhishek Sur11-Aug-09 22:16
professionalAbhishek Sur11-Aug-09 22:16 
GeneralRe: Example request Pin
Mohammed Aziz Elnahrawi28-May-10 23:37
Mohammed Aziz Elnahrawi28-May-10 23:37 
GeneralWhat' a about user serving speed Pin
Hristo-Bojilov27-Jul-09 22:41
Hristo-Bojilov27-Jul-09 22:41 
GeneralRe: What' a about user serving speed Pin
Abhishek Sur28-Jul-09 22:19
professionalAbhishek Sur28-Jul-09 22:19 
GeneralRe: What' a about user serving speed Pin
Andre Sanches (alvs)13-Aug-09 12:29
Andre Sanches (alvs)13-Aug-09 12:29 
I beg to differ, the article provides the means to implement HTTP compression independently for each page as opposed to the "either all or nothing" method that IIS offers. This gives you the opportunity to fine tune your application and only compress the pages that are lighter in terms of processing requirement and leave the heavier ones uncompressed. In addition you could also just as easily set a boolean key in your app configuration to either enable or disable compression, and if your servers start crapping out because of cpu utilization you can just flip the switch.

The article certainly deserves more than a 3. My only suggestion would be to implement the means to control the compression level (higher compression -> higher cpu utilization and vice-versa), which will give the user an even finer grained control for tuning the extra overhead.

---------
Andre Sanches

"UNIX is friendly, it's just picky about its friends"

GeneralPlease send me an example. Pin
lisekR27-Jul-09 4:48
lisekR27-Jul-09 4:48 
GeneralRe: Please send me an example. Pin
Abhishek Sur27-Jul-09 12:45
professionalAbhishek Sur27-Jul-09 12:45 
GeneralCool Buddy Pin
Abhijit Jana26-Jul-09 13:24
professionalAbhijit Jana26-Jul-09 13:24 
GeneralRe: Cool Buddy Pin
Abhishek Sur26-Jul-09 21:44
professionalAbhishek Sur26-Jul-09 21:44 
GeneralNice just a few questions Pin
spoodygoon26-Jul-09 6:36
spoodygoon26-Jul-09 6:36 

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

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