How to achieve simple URL-based routing to services in IIS

Did you know you can run multiple services or components under the same domain using IIS, even if the individual services are using completely different technologies, operating systems, or hosting platforms?  In a microservices, service-orientated architecture (SOA) or other distributed systems scenario, this is useful for providing a common, neat resource structure. Most “front-end” web servers provide this type of routing service by acting as a reverse proxy – nginx is a common contender – but IIS on Windows is no exception.

So, how’s it done? First we’ll need to set up IIS to support reverse-proxying based on URLs. We need the URL Rewrite and ARR features, which require IIS 7.0 or newer.

  1. Open Web Platform Installer (“Web PI”) – if you don’t have this, you can download from here
  2. Search for and install URL Rewrite 2.0
  3. Search for and install Application Request Routing 3.0
  4. Open IIS Manager (Start, Run, inetmgr)
  5. Double-click the Application Request Routing node and click Server Proxy Settings on the right-hand side
  6. Tick “Enable proxy”

Next, create a Site in IIS that will listen on the appropriate port for the host header you’re interested in. Set up the physical path to a new folder which will hold your custom web.config file.

You can then create a web.config outlining each of the routing rules you have in mind. Here’s an example which demonstrates simple path-based routing to two different sites:

                <rule name="site1" stopProcessing="true">
                    <match url="^site1/(.*)"/>
                        <add input="{CACHE_URL}" pattern="^(https?)://"/>
                    <action type="Rewrite" url="{C:1}://{R:1}"/>
                <rule name="site2" stopProcessing="true">
                    <match url="^site2/(.*)"/>
                        <add input="{CACHE_URL}" pattern="^(https?)://"/>
                    <action type="Rewrite" url="{C:1}://{R:1}"/>

As you can see, each rule has a regular expression tested against the URL in the “match” element. The “action” element indicates what to do, and in this case we use “conditions” to test and capture the protocol (http or https) to retain it during rewriting.

In the above example, we route any requests whose path begins “site1/” to the “” host and “site2/” to the “” host.

In this case, we’re using “{R:1}” for the path. This takes value of the explicit (bracketed) group within our regex – the part after the “site1/” prefix, and so the request to the back-end service will NOT include the “site1/” prefix. If we wanted to retain the path, use “{R:0}” instead, which captures the whole request URL.

Configuration reference can be found in the URL Rewrite Module Configuration Reference. For a more in-depth guide, covering scenarios such as those where you need to modify the response from the web server – for example, if you’re proxying to a web site (rather than service), and need the links and images to be rewritten too – check out this CarlosAg post on MSDN.

We use this technique on our own Windows development machines, and in production for a project where the system is implemented by two main services – one .NET Core in a Docker container running on a Linux app service on Azure, the other a standard ASP.NET Web API project.  The downside to this approach is that it needs you to be responsible for the VM running IIS – provisioning, configuring and monitoring it manually.  However in this case we have such a server to hand and this little trick helps us realise a consistent approach to separate services quickly and easily.

Leave a Reply

Your email address will not be published. Required fields are marked *

More to Explore