Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to enable gzip HTTP compression on Windows Azure dynamic content

I've been trying unsuccessfully to enable gzip HTTP compression on my Windows Azure hosted WCF Restful service which returns JSON only from GET and POST requests.

I have tried so many things that I would have a hard time listing all of them, and I now realise I have been working with conflicting information (regarding old version of azure etc) so think it best to start with a clean slate!

I am working with Visual Studio 2008, using the February 2010 tools for Visual Studio.

So, according to the following link..

.. HTTP compression has now been enabled. I've used the advice at the following page (the URL compression advice only)..

http://blog.smarx.com/posts/iis-compression-in-windows-azure

<urlCompression doStaticCompression="true"           doDynamicCompression="true"          dynamicCompressionBeforeCache="true"  /> 

.. but I get no compression. It doesn't help that I don't know what the difference is between urlCompression and httpCompression. I've tried to find out but to no avail!

Could, the fact that the tools for Visual Studio were released before the version of Azure which supports compression, be a problem? I have read somewhere that, with the latest tools, you can choose which version of Azure OS you want to use when you publish ... but I don't know if that's true, and if it is, I can't find where to choose. Could I be using a pre-http enabled version?

I've also tried blowery http compression module, but no results.

Does any one have any up-to-date advice on how to achieve this? i.e. advice that relates to the current version of the Azure OS.

Cheers!

Steven

Update: I edited the above code to fix a type in the web.config snippet.

Update 2: Testing the responses using the whatsmyip URL shown in the answer below is showing that my JSON responses from my service.svc are being returned without any compression, but static HTML pages ARE being returned with gzip compression. Any advice on how to get the JSON responses to compress will be gratefully received!

Update 3: Tried a JSON response larger than 256KB to see if the problem was due to the JSON response being smaller than this as mentioned in comments below. Unfortunately the response is still un-compressed.

like image 787
Steven Elliott Avatar asked May 05 '10 17:05

Steven Elliott


People also ask

How do I enable gzip compression?

It's also one of the two recommended web servers by WordPress. To enable GZIP compression on Apache servers, you need to use its mod_filter and mod_deflate modules and configure them properly with the right directives. They will direct Apache to compress server output before sending it to clients over the network.

How do I enable dynamic content compression?

In Control Panel, click Programs and Features, and then click Turn Windows features on or off. Expand Internet Information Services, expand World Wide Web Services, expand Performance Features, and then select Dynamic Content Compression and/or Static Content Compression. Click OK. Click Close.

How do you check gzip compression is enabled or not?

Double click on the file and select headers. Under 'Response headers' you are looking for the 'Connection-Encoding' field, it will say gzip if it is enabled.


2 Answers

Well it took a very long time ... but I have finally solved this, and I want to post the answer for anyone else who is struggling. The solution is very simple and I've verified that it does definitely work!!

Edit your ServiceDefinition.csdef file to contain this in the WebRole tag:

    <Startup>       <Task commandLine="EnableCompression.cmd" executionContext="elevated" taskType="simple"></Task>     </Startup> 

In your web-role, create a text file and save it as "EnableCompression.cmd"

EnableCompression.cmd should contain this:

%windir%\system32\inetsrv\appcmd set config /section:urlCompression /doDynamicCompression:True /commit:apphost %windir%\system32\inetsrv\appcmd set config  -section:system.webServer/httpCompression /+"dynamicTypes.[mimeType='application/json; charset=utf-8',enabled='True']" /commit:apphost 

.. and that's it! Done! This enables dynamic compression for the json returned by the web-role, which I think I read somewhere has a rather odd mime type, so make sure you copy the code exactly.

like image 51
Steven Elliott Avatar answered Oct 04 '22 16:10

Steven Elliott


Well at least I'm not alone on this one - and it's still a stupid PITA almost a year later.

The problem is a MIME type mismatch. WCF returns JSON response with Content-Type: application/json; charset=UTF-8. The default IIS configuration, about halfway down that page, does not include that as a compressible MIME type.

Now, it might be tempting to add an <httpCompression> section to your web.config, and add application/json to that. But that's just a bad way to waste a good hour or two - you can only change the <httpCompression> element at the applicationHost.config level.

So there are two possible solutions. First, you could change your WCF response to use a MIME type that is compressible in the default configuration. text/json will work so adding this to your service method(s) will give you dynamic compression: WebOperationContext.Current.OutgoingResponse.ContentType = "text/json";

Alternatively, you could change the applicationHost.config file using appcmd and a startup task. This is discussed (among other things) on this thread. Note that if you add that startup task and run it in the dev fabric, it will work once. The second time it will fail because you already added the configuration element. I ended up creating a second cloud project with a separate csdef file, so that my devfabric would not run that startup script. There are probably other solutions though.

Update

My suggestion for separate projects in the previous paragraph is not really a good idea. Non-idempotent startup tasks are a very bad idea, because some day the Azure fabric will decide to restart your roles for you, the startup task will fail, and it'll go into a recycle loop. Most likely in the middle of the night. Instead, make your startup tasks idempotent as discussed on this SO thread.

like image 38
Brian Reischl Avatar answered Oct 04 '22 16:10

Brian Reischl