Sysadmins of the North

Technical blog, where topics include: computer, server, web, sysadmin, MySQL, database, virtualization, optimization and security

IIS Outbound Rules with gzip compression

Saotn.org uses used URL Rewrite Outbound Rules in IIS, to offload content from a different server and/or host name. This should improve website performance. Just recently I noticed Outbound Rules conflicted with gzip compressed content. I started noticing HTTP 500 error messages: Outbound rewrite rules cannot be applied when the content of the HTTP response is encoded ("gzip").. Here is how to fix that error.

Fix for Outbound rewrite rules cannot be applied when the content of the HTTP response is encoded (“gzip”).

Searching Google (search query) there is a number of reports and possible solutions.

Some of the solutions included the steps:

  1. Set the LogRewrittenUrlEnabled registry key:
    reg add HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\InetStp\Rewrite /v LogRewrittenUrlEnabled /t REG_DWORD /d 0
  2. Make sure that dynamicCompressionBeforeCache property is set to false for the /system.webServer/urlCompression configuration element.
  3. Re-order the IIS modules to have URL Rewrite run before Dynamic Compression module (DynamicCompressionModule). In the IIS Manager user interface in the modules’s ordered view the Dynamic Compression module should be above the URL Rewrite module.

But I didn’t want to fiddle with the registry, which I’m sure you can imagine.

The Stack Overflow post IIS as a reverse proxy – compression of rewritten response from backend server was what really set me on the right track.

This is how I fixed the Outbound Rules with gzip compressed content on IIS 7.5 / IIS 8.0:

Through the IIS Manager GUI, add two Allowed Server Variables:

  1. HTTP_ACCEPT_ENCODING
  2. HTTP_X_ORIGINAL_ACCEPT_ENCODING

Ask your administrator if you don’t have access. We use these server variables to store the contents of HTTP_ACCEPT_ENCODING into HTTP_X_ORIGINAL_ACCEPT_ENCODING, right before we remove the HTTP_ACCEPT_ENCODING header. Removing this header is necessary.

Then, in your web.config file set up the inbound and outbound rewrite rules:

  1. Add an outboundRule to restore the HTTP_ACCEPT_ENCODING header with the contents of HTTP_X_ORIGINAL_ACCEPT_ENCODING.
  2. Add a preCondition required by the outboundRule.

Putting this all together, I came up with the following web.config URL Rewrite rules:

<rewrite>
  <rules>
    <rule name="wordpress" patternSyntax="Wildcard">
      <match url="*"/>
    <conditions>
      <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true"/>
      <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true"/>
    </conditions>
    <serverVariables>
      <set name="HTTP_X_ORIGINAL_ACCEPT_ENCODING" value="{HTTP_ACCEPT_ENCODING}" />
      <set name="HTTP_ACCEPT_ENCODING" value=""/>
    </serverVariables>
      <action type="Rewrite" url="index.php"/>
     </rule>
  </rules>

  <outboundRules rewriteBeforeCache="true">
    <rule name="RestoreAcceptEncoding" preCondition="NeedsRestoringAcceptEncoding">
      <match serverVariable="HTTP_ACCEPT_ENCODING" pattern="^(.*)" />
      <action type="Rewrite" value="{HTTP_X_ORIGINAL_ACCEPT_ENCODING}" />
    </rule>
    <preConditions>
      <preCondition name="NeedsRestoringAcceptEncoding">
    <add input="{HTTP_X_ORIGINAL_ACCEPT_ENCODING}" pattern=".+" />
      </preCondition>
    </preConditions>
  </outboundRules>
</rewrite>

Disclamer: This works for my set up, it may not work for yours. I’d love to hear your response!

Previous

MySQL in WordPress 3.9

Next

“Node.js Performance Tip of the Week: Scaling with Proxies and Clusters”

6 Comments

  1. Alin Vina

    Man i just want to thank you a million time for this. Ive been working on this for a week, and i found this blog in the last minute of the day and got it working before my vacation.
    I just wanted you to know that you made an engineer very happy with this post, and that it’s a great personal Christmas gift for me that i managed to solve it.
    Merry Christmas !!

    • Hi Alin,
      Great to hear the post solved the problem you were facing! I wish you a merry Christmas and a wonderful Holiday Season!

  2. Paul d'Aoust

    Hm, I feel like I’m missing part of your formula. I’ve got all these things in place, and yet I’m still not seeing any compression for proxied content. What’s the ordering of your IIS modules? Does it matter where `HttpCacheModule` and `RewriteModule` are in relation to `DynamicCompressionModule` and `StaticCompressionModule`?

    • Hi Paul. Thank you for your comment and my apologies for my late reaction.

      Most information in this post comes from piecing together bits and pieces from StackOverflow (https://stackoverflow.com/questions/15926203/iis-as-a-reverse-proxy-compression-of-rewritten-response-from-backend-server) and my own web.config (search query on Saotn.org).

      Maybe the StackOverflow post sheds some extra light on the issue you’re facing?

      • Paul d'Aoust

        Hi, Jan. Thanks for taking the time to get back to me! I forgot I’d commented on your article.

        I did look through that SO post and I still couldn’t get my setup to work. But I eventually realised I wasn’t doing any response body rewriting, so I just left the Accept-Encoding header alone and it worked!

      • Paul d'Aoust

        (That is, I had an outbound rule that did rewrite the response body (changed app server relative URLs to public server relative URLs), but it never actually was necessary because (a) the backend app server always knew about the frontend server’s hostname, and (b) we hardly used absolute URLs that needed rewriting anyway!)

Hi! Join the discussion, leave a reply!

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Powered by WordPress & Theme by Anders Norén

%d bloggers like this:
W JezeSjNO jIX