43

I am using the answer given here as the basis for trying to add a rewrite rule to my web.config file. I want it to match any url that is not running on localhost in order to force https.

Here is what I have right now:

<system.webServer>
  <rewrite> <!-- force https - https://stackoverflow.com/a/15119044/51 -->
    <rules>
      <rule name="Redirect HTTP to HTTPS" stopProcessing="true">
        <match url="^((?!localhost).)*$"/>
        <conditions>
          <add input="{HTTPS}" pattern="^OFF$"/>
        </conditions>
        <action type="Redirect" url="https://{HTTP_HOST}/{R:1}" redirectType="SeeOther"/>
      </rule>
    </rules>
  </rewrite>
</system.webServer>

I am trying to use a negative lookaround in order to only match url's that do not include "localhost" within the url. But this is not working.

So how should this rule be set up in order to only rewrite non-localhost url's?

Community
  • 1
  • 1
Yaakov Ellis
  • 40,752
  • 27
  • 129
  • 174

3 Answers3

59

Try this condition:

<system.webServer>
  <rewrite>
    <rules>
      <rule name="Redirect HTTP to HTTPS" stopProcessing="true">
        <match url="^(.*)$"/>
        <conditions>
          <add input="{HTTPS}" pattern="^OFF$"/>
          <add input="{HTTP_HOST}" matchType="Pattern" pattern="^localhost$" negate="true" /> 
        </conditions>
        <action type="Redirect" url="https://{HTTP_HOST}/{R:1}" redirectType="SeeOther"/>
      </rule>
    </rules>
  </rewrite>
</system.webServer>

Using a negate condition against the localhost pattern should do the trick.

Yaakov Ellis
  • 40,752
  • 27
  • 129
  • 174
anubhava
  • 761,203
  • 64
  • 569
  • 643
58

Adding to anubhava's answer, you can replace the add element for localhost with the following 2 entries to cater for both localhost and 127.0.0.1 with optional ports e.g localhost:59400 which is the case when debugging through visual studio and IIS

<add input="{HTTP_HOST}" matchType="Pattern" pattern="^localhost(:\d+)?$" negate="true" />
<add input="{HTTP_HOST}" matchType="Pattern" pattern="^127\.0\.0\.1(:\d+)?$" negate="true" />    

With the original answer, localhost:123 would be redirected to https which may not be desirable.

Community
  • 1
  • 1
Sam Sippe
  • 3,160
  • 3
  • 27
  • 40
  • 2
    this one worked for me. anubhava's answer doesn't consider the localhost:XXXX case (port) – sports Aug 19 '16 at 16:37
  • 4
    this works for me except if I navigate to root ("/"). then for some reason it is redirecting me to HTTPS. – Mike W Mar 23 '17 at 13:17
  • 1
    @MikeW I am getting the same issue when navigating to root. Not sure how to fix that. – drewid Jul 09 '17 at 23:24
  • 2
    here is my entire rule - seems to be working... – Mike W Jul 10 '17 at 20:50
  • @drewid I had the same problem accessing root & resolved it by setting the following attribute on the conditions element: logicalGrouping="MatchAll". So now my element is: – Carl Heinrich Hancke Jul 19 '17 at 10:16
  • Can you also provide an example with a specific port number? like http://localhost:15536 – Lucas Matos Jan 27 '21 at 21:39
  • @MikeW maybe your browser cached a previous redirect? In my case, clearing the browser cache fixed the issue. I read in a blog post: "Always remember when you debug a redirect (specifically a 301) that browsers tend to cache them and that it can lead to frustration when you change the rule but nothing happens…" see here: https://nicolas.guelpa.me/blog/2015/02/21/rewrite-redirect-iis.html – Hermann.Gruber Oct 19 '21 at 12:31
0

Regular expression updated, this works for me, with a custom Port

<add input="{HTTPS}" pattern="off" ignoreCase="true" />
<add input="{HTTP_HOST}" matchType="Pattern" pattern="(localhost)(:\d+)" negate="true" />
<add input="{HTTP_HOST}" matchType="Pattern" pattern="(127.0.0.1)(:\d+)" negate="true" />
Lucas Matos
  • 2,531
  • 2
  • 15
  • 17
  • Nitpick: the dots have special meaning in POSIX regular expressions, and need to be escaped. So 127.0.0.1 should be 127\.0\.0\.1 – Hermann.Gruber Oct 19 '21 at 08:31