16
votes

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?
2
Just checking, have you definitely got the text right in item 2 above - that mysite.com redirects successfully to https://www.mySite.com? - Jon Egerton
They're not case sensitive are they? - in some places you've used mySite, in others mysite (for example in item 3). - Jon Egerton
i just used address www.mysite.com instead of my actual address :) - Jernej Gorički
Of course, just wondered if you had the same in your real config. - Jon Egerton
Are you sure it fails to redirect, or do you just mean the browser is warning about SSL certificate name does not match before the redirect happens? Depending on how your SSL cert is setup, you may get that warning with or without the redirect, and if so, it will most likely happen before the redirect. If this is the case, try the "continue anyway" option on the warning and see if it redirects afterwards. - eselk

2 Answers

26
votes

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.

7
votes

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>