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 WhitespaceFilter(context.Response.Filter,
CompressOptions.GZip);
response.AppendHeader("Content-encoding", "gzip");
}
else if (acceptEncoding.Contains("DEFLATE"))
{
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.
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