Azure App Services: Understanding URL Re-write

Introduction:

More often than not, we come across requirements with our Azure App Service where we may need to enforce HTTPS, redirect from *.com to *.in, redirect  from https://abc.com to https://www.abc.com and so on...

The requirements can be tricky sometimes. Formulating such rules, and ensuring they're both logically and syntactically correct can be a little time consuming. I’ve shared below a few pointers that you can use to formulate such re-write rules and avoid your site from going offline due to trial and errors on a live site.

Some background on URL Re-write:

Azure App Service (PaaS) is nothing but IIS Servers placed on the cloud. Therefore, URL Re-write on Azure App Service works a lot like IIS .

Where does URL-Rewrite fit in IIS Architecture?

[caption id="attachment_25" align="aligncenter" width="413"]Where does URL-Rewrite fit in IIS Architecture URL-Rewrite's place in IIS Architecture[/caption]

How is re-write different from Redirect?

Rewrite Redirect
Happens at the Server Side Happens at the Client Side
Browser does not see new URL in address bar Browser sees a different URL In address bar
Client unaware if content is served from a re-written URL Client aware of a redirect URL.
You can re-write https://wawsin.in/article/test-sub/ to https://wawsin.in/article.aspx?id=test-sub and the client still sees the friendly URL https://wawsin.in/article/test-sub/ You can redirect from https://wawsin.in/home to https://www.wawsin.in/myHome and the browser shows the news URL https://www.wawsin.in/myHome
Generally for a resource within same site. Can be redirected to same site or different site altogether.
Request Handling (REWRITE): https://wawsin.in/article/test-sub/ which you want to point to https://wawsin.in/article.aspx?id=test-sub
  1. Client calls: https://wawsin.in/article/test-sub/
  2. URL Rewrite Module sees a rule match and provides new rewritten URL to IIS i.e. https://wawsin.in/article.aspx?id=test-sub and Server makes request for that URL within IIS.
  3. Server responds with 200 OK for original URL but with content from rewritten URL. (address bar shows original URL and client does not know that you are serving content from different URL)
 
Request Handling (REDIRECT): https://wawsin.in/home to redirect to https://www.wawsin.in/myHome1.       Client calls: https://wawsin.in/home2.       URL Rewrite Module sees a rule match for client URL and gives new redirect URL.3.       Server responds with 301 with new URL for client to call https://www.wawsin.in/myHome4.       Client calls new URL https://www.wawsin.in/myHome5.       Server responds with 200 OK for new URL. (address bar shows new URL) 

Common Scenarios:

1. Enforce HTTPS:

  <rule name="HTTP_TO_HTTPS" stopProcessing="true">
<match url=".*" />
<conditions>
<add input="{HTTP_HOST}" pattern="^www.wawsin.in$" />
<add input="{HTTPS}" pattern="OFF" />
</conditions>
<action type="Redirect" url="https://{C:0}/{R:0}" />
</rule>

NOTE:   It is important to use Redirect here since the request needs to come back to the server over HTTPS.

2.  In case there are multiple domains associated with the Web App and you want to enforce HTTPS on all of them:

<rule name=" HTTP_TO_HTTPS " stopProcessing="true">
<match url=".*" />
<conditions>
<add input="{HTTPS}" pattern="OFF" />
<add input="{HTTP_HOST}" pattern="(^www.wawsin.in$)|(^waswin.in$)" />
</conditions>
<action type="Redirect" url="https://{C:0}/{R:0}" />
</rule>

3. Redirection from root domain to sub-domain:

<rule name="Root_To_Subdomain " stopProcessing="true">
<match url=".*" />
<conditions>
<add input="{HTTP_HOST}" pattern="^wawsin.in$" />
</conditions>
<action type="Redirect" url="https://www.{C:0}/{R:0}" />
</rule>

NOTE:   It is important to use Redirect (send the modified request back to the client) here since it is necessary to validate if the sub-domain is mapped to the same Web App.

4. Redirect from www.wawsin.com to www.wawsin.in , www.wawsin.org to www.wawsin.in, www.wawsin.net to www.wawsin.in , wawsin.org to www.wawsin.in and so on…

  <rule name="Change-TLD" stopProcessing="true">
<match url=".*" />
<conditions logicalGrouping="MatchAny">
<add input="{HTTP_HOST}" pattern="(.*).com" />
<add input="{HTTP_HOST}" pattern="(.*).org" />
<add input="{HTTP_HOST}" pattern="(.*).net" />
</conditions>
<action type="Redirect" url="https://{C:1}.in/{R:0}" />
</rule>

NOTE:  

a. We can use (.*).com here to accommodate both www.wawsin.in and wawsin.in.
b. logicalGrouping="MatchAny" will only match one of the conditions that succeed it. logicalGrouping="MatchAll" by default.

Some useful stopping Conditions:

Stopping conditions are very important in order to avoid too-many-redirects caused due the same request being processed every time (Re-write --> Send to client --> Client requests re-written URL from the server --> No Appropriate stopping condition --> Rule processed again --> Re-write…and this cycle repeats)

To avoid such scenarios, you want to formulate rules that have a logical stopping condition. The below pointers may be useful:

<add input="{HTTPS}" pattern="OFF" /> Process the rule if the request does not come over HTTPS
<add input="{HTTPS}" pattern="ON" negate="true" /> Process the rule if the request comes over HTTP only. Same as above.
<add input="{HTTP_HOST}" pattern="^www.wawsin.in$" negate="true" /> Process the rule for all other domains except for www.wawsin.in

Want to know how to test your rules for perfection while avoiding production downs? A blog on that is coming soon..