I have been working on getting gzip/deflate compression working on Web API responses. I have been using the code from Github - MessageHandlers.Compression. However it didn't appear to work. There was no Content-Encoding header appearing in the Google Developer console or in Firebug in Firefox and the Content-Length was consistently set to the uncompressed size of the data. So I kept stripping out the code until I ended up with the following:
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
// Send the request to the web api controller
var response = await base.SendAsync(request, cancellationToken).ConfigureAwait(false);
// Compress uncompressed responses from the server
if (response.Content != null && request.Headers.AcceptEncoding.IsNotNullOrEmpty())
{
var content = response.Content;
var bytes = content.ReadAsByteArrayAsync().Result;
if (bytes != null && bytes.Length > 1024)
{
// The data has already been serialised to JSon by this point
var compressedBytes = Compress(bytes);
response.Content = new ByteArrayContent(compressedBytes);
var headers = response.Content.Headers;
headers.Remove("Content-Type");
headers.ContentLength = compressedBytes.Length;
headers.ContentEncoding.Clear();
headers.ContentEncoding.Add("gzip");
headers.Add("Content-Type", "application/json");
}
}
return response;
}
private static byte[] Compress(byte[] input)
{
using (var compressStream = new MemoryStream())
{
using (var compressor = new GZipStream(compressStream, CompressionMode.Compress))
{
compressor.Write(input, 0, input.Length);
compressor.Close();
return compressStream.ToArray();
}
}
}
When I initially did this I made a mistake, and set the content encoding in the header to 'gzip' when I used a DeflateStream in the Compress method. As you would expect I got an error in the browser, however the response headers were correct(!). That is, the Content-Encoding header was set and the Content-Length was correct. As well, looking at the raw data I could clearly see if was compressed. As soon as I corrected my error though the problem returned.
What I am wondering is do the latest versions of the browser decompress the content behind the scenes, or is there actually something wrong with my code? Responses are sent in Json format
Any help much appreciated.
EDIT
I tried dumping the headers to a log file in the following methods in Global.asax (listed in the order they appeared in the log):
Application_PreSendRequestHeaders
Application_EndRequest
Application_PreSendRequestContent
In each case the required headers were there, even though they didn't appear in the Google developer console. I then took a look at the solution at Code Project. When run from the command line everything worked as anticipated. However when I called the web server from Google Chrome I got the exact same result. That is, no Content-Encoding header, and no indication as to whether the content had been compressed or not. However with the developer console open it's easy to see this header at other sites (stack overflow for instance). I have to assume this is therefore something to do with compressed responses from web api services. It's so hard to know though if this is actually working client side.