I recently had to install and configure a reverse proxy using IIS and the URL rewrite extension. At first glance it seemed a pretty straight forward task to set up target location for the redirection, but it turned out not being as simple as that.

Step 1: understanding what URL rewrite do

URL rewrite is an IIS extension that can be downloaded here: http://www.iis.net/downloads/microsoft/url-rewrite Basically, it allows the rewriting of any URI on the fly (hence the name) in both directions (inbound and outbound). As such, it is a great tool for a reverse proxy, when all you want is to forward the request made to http://www.proxy.com/domain/soft1 to http://soft1/ for example. Each request follows the sequence diagram described in Figure 1.

URL Rewrite - Fig1

Figure 1 URL rewrite in action

So, in order to set up a proper redirection, you basically have two things to do:

  1. Set up the inbound rules, that will translate the public address of you service (here http://www.proxy.com/domain/soft1 ) to your internal address (here http://soft1)
  2. Set up the outbound rules that will correct relative and absolute links in the soft1 server answers so that they can be requested by the client

In both cases, a rule is nothing but a glorified way to do a String.Replace in the request/response.

Step 2: writing inbound rules

Inbound rules are here to translate the request coming from the client, using a publicly available address, to a request going to an internal and not exposed server, while preserving the part of the request that does not need translation.

URL Rewrite - Fig2

Figure 2 Inbound rule sample

  There are some key points:

  • In a great majority of cases, you want to set the HTTP_ACCEPT_ENCODING server variable to blank. This is because you’ll probably have to write outbound rules to rewrite the links in the responses. And you cannot do that if the response is compressed, so better remove the “gzip/deflate” flags from the accept_encoding part of the header, right? Note that, in order to be able to replace a server variable, you have to register it in the, guess what, View server variable screen.
  • While the default pattern (which is ^/(.*)) is sufficient in the vast majority of cases, you may have to deal with some mechanism that needs other pattern (such as the ASP.Net forms authentication mechanism and its returnurl parameter). In this case, you’ll have to write several rules: one for each of the particular cases, using a specific pattern (for ASP.Net it will be something like ^/(.*)\?returnurl=/(.*)\?(.*)) and finally the catch-all rule. Do not forget to set the Stop processing of subsequent rules flag on each one!
  • Do not forget that you are not limited to rewrite to a site root. You can, for example, redirect to http://soft1/Appli/{R:1} or even pass the input URI as a parameter such as http://soft1/query.aspx?uri={R:1}
  • If you specify explicitly the http:// prefix in the rewrite URL, you effectively add SSL offloading to your reverse proxy. If you want to keep the encryption, you have to add a condition on {CACHE_URL} with pattern ^(https?):// and start the rewrite URL by {C:1}://

Step 3: Writing outbound rules

Outbound rules are here to modify the response sent by the server so that the links within point to your reverse proxy instead of pointing to the real server. That concerns absolute links (change http://soft1/icon.png to http://www.proxy.com/domain/soft1/icon.png) or relative links (change /icon.png to /domain/soft1/icon.png) Why is that needed? Well, consider what will happen if you don’t do it:

  1. The client request http://www.proxy.com/domain/soft1
  2. Inbound rule triggers and rewrite it to http://soft1/
  3. The soft1 server answers with an http page containing a <img src=”/icon.png”/>
  4. The client request http://www.proxy.com/icon.png
  5. 404 – page not found !

So basically, unless you have a single page application, you’ll need to rewrite some links. And that’s why there are outbound rules!

 URL Rewrite - Fig3

Figure 3 Outbound rules samples

 As for inbound rules; some key points:

  • You’ll need at least one rule for relative paths (pattern ^/(.*)) and one for absolute paths (pattern ^http://soft1/(.*))
  • You can rewrite absolute path to relative ones. For example, translating ^http://soft1/(.*) to /domain/soft1/{R:1}
  • By default, a rule works only in the defined tags within the body of the response. If you do not specify a tag, it does a global search and replace, which is useful if you need to change the content of a javascript variable, for example.
  • If you want to be able to rewrite 30x responses (redirect/rewrite), for example to be able to chain reverse proxies, you’ll have to add a rule with replace the server variable RESPONSE_Location

Livre Blanc Cell'insight 1 DevOps