Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

IIS URL Rewriting: Enforce canonical hostname & HTTP to HTTPS redirect

Tags:

asp.net

iis

I'm using these two rules in my web.config file:

<rule name="Enforce canonical hostname" stopProcessing="true">
      <match url="(.*)" />
      <conditions>
        <add input="{HTTP_HOST}" negate="true" pattern="^www\.example\.com$" />
      </conditions>
      <action type="Redirect" url="https://www.example.com/{R:1}" redirectType="Permanent" />
    </rule>
    <rule name="HTTP to HTTPS redirect" stopProcessing="true">
      <match url="(.*)" />
      <conditions>
        <add input="{HTTPS}" pattern="off" ignoreCase="true" />
      </conditions>
      <action type="Redirect" redirectType="Found" url="https://{HTTP_HOST}/{R:1}" />
    </rule>

With these two rules I get the following Redirect to work :

  1. http://www.example.com ---> https://www.example.com
  2. http://example.com--->https://www.example.com
  3. https://example.com ---> this fails to redirect to https://www.example.com ... Why?
like image 691
Jernej Gorički Avatar asked Feb 02 '12 11:02

Jernej Gorički


People also ask

How does IIS URL Rewrite work?

Each rewrite rule analyzes the URL path and, if all the rule conditions are met, changes the original path to a new path. After all the rules have been evaluated, the URL Rewrite module produces a final URL path that is used for the request through the remainder of the IIS pipeline processing.

What is the difference between routing and URL rewriting?

URL rewriting is focused on mapping one URL (new url) to another URL (old url) while routing is focused on mapping a URL to a resource. Actually, URL rewriting rewrites your old url to new one while routing never rewrite your old url to new one but it map to the original route.


2 Answers

Not sure if you're still seeking an answer but here goes. After some searching, and trial and error, I found success with the following rules. Most examples I've encountered are unnecessarily complex with regards to pattern matching and introduce other variables that prevent the rules from working as intended. The rules below can be applied to any website, and nothing is hard-coded so it should always be a straight copy-and-paste job:

<rule name="Redirect to WWW" stopProcessing="true" >
    <match url="(.*)" />
    <conditions>
        <add input="{HTTP_HOST}" pattern="^www\." negate="true"/>
    </conditions>
    <action type="Redirect" url="https://www.{HTTP_HOST}{HTTP_URL}" redirectType="Permanent" appendQueryString="false" />
</rule>
<rule name="Redirect to HTTPS">
    <match url="(.*)" />
    <conditions>
        <add input="{HTTPS}" pattern="OFF"/>
    </conditions>
    <action type="Redirect" url="https://{HTTP_HOST}{HTTP_URL}" redirectType="Permanent" appendQueryString="false" />
</rule>

Two things to note: redirectType="Permanent" will will result in the rule being applied until the browser's history / cache are emptied; this should be a good thing as the browser would do the work going forward. Also, appendQueryString="false" is necessary as the {HTTP_URL} server variable already includes the full querystring; by default the option is "true" and would result in duplicate querystrings here.

like image 73
PeteyPablo Avatar answered Oct 22 '22 14:10

PeteyPablo


If it's for anyone's benefit, here's the same thing obtained with only one rule:

<rule name="Redirect HTTP to HTTPS and non-WWW to WWW" stopProcessing="true">
    <match url="(.*)"/>
    <conditions trackAllCaptures="false" logicalGrouping="MatchAny"> <!-- match non-HTTPS or non-WWW -->
        <add input="{HTTPS}" pattern="^OFF$"/> <!-- if connection not secure -->
        <add input="{HTTP_HOST}" matchType="Pattern" ignoreCase="true" pattern="^example\.com$" /><!-- domain is not canonical  -->
    </conditions>
    <action type="Redirect" url="https://www.example.com{HTTP_URL}" redirectType="Permanent" appendQueryString="false"/>
</rule>
like image 22
CyberDude Avatar answered Oct 22 '22 13:10

CyberDude