Umbraco https rewrite rule causes an infinite loop - iis-7

I have the following rewrite rule that works perfectly fine on a regular asp.net project, running on IIS7.
<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>
So one of our pages when visited at http://{domain}/aboutus will redirect to https://{domain}/aboutus. Now putting the same rewrite rule in an Umbraco site causes an infinite loop. We don't have any other rewrite rule for our Umbraco site. That leads me to think that Umbraco is somewhat hijacking the routing from http to https and causes the infinite loop. What are we missing?

I recommend using the following rule instead:
<rule name="Redirect to https" stopProcessing="true">
<match url="(.*)" />
<conditions>
<add input="{HTTPS}" pattern="off" ignoreCase="true" />
</conditions>
<action type="Redirect" url="https://{HTTP_HOST}{REQUEST_URI}"
redirectType="Permanent" appendQueryString="false" />
</rule>

As your regex for url isn't filters the input (<match url="(.*)" />), you should use redirectType="Permanent" parameter in your code:
More information can be found here:
Add an Url Rewrite rule
One thing worth noting is that by default the re-directs are 302 re-directs, if you want to do 301 re-directs you need to add the following:
redirectMode="Permanent"
You can find the full instructions for the URL re-writing component on their website:
https://github.com/aspnetde/UrlRewritingNet

One potential solution is to use the Umbraco rewrite module rather than an IIS rewrite.
In the URL rewriting config file (Config/UrlRewriting.config), the following rule is a simple example of how to redirect from HTTP to HTTPS:
<add name="https Rewrite"
redirect="Domain"
redirectMode="Permanent"
virtualUrl="http://(.*)"
destinationUrl="https://$1"
ignoreCase="true" />
This rule should be placed within the <rewrites> section.
Edit: As per sebastiaan's comment, the urlRewriting.net module is outdated and an IIS solution should be used where possible.

I also have had issues with infinite redirect loops with Umbraco 6.2.4. It was occurring randomly every week or so. My site is all SSL, with UmbracoUseSSL = false.
My HTTP to HTTPS rules was as follows:
<rule name="Redirect to https" stopProcessing="true">
<match url="(.*)" />
<conditions>
<add input="{HTTPS}" pattern="off" ignoreCase="true" />
</conditions>
<action type="Redirect" url="https://{HTTP_HOST}/{R:1}" redirectType="Permanent" />
I updated to the following per #sebastiaan
<rule name="Redirect to https" stopProcessing="true">
<match url="(.*)" />
<conditions>
<add input="{HTTPS}" pattern="off" ignoreCase="true" />
</conditions>
<action type="Redirect" url="https://{HTTP_HOST}{REQUEST_URI}"
redirectType="Permanent" appendQueryString="false" />
Sounds like since R:1 can contains an empty string, it has the potential to cause loops. {REQUEST_URI} will always contain at least a slash. Not sure if that is why #sebastiaan recommends the latter?
If the problem persists, I'll report back. Hopefully the updated rule will resolve the issue.

Related

Combine several 301 redirects into one for ASP.NET URL Rewrite module

I am trying to move a complex redirect logic implemented in Global.asax into a set of rules for the IIS URL Rewrite module in a classic ASP.NET website. Shortly, the logic must redirect requests like
{http|https}://[www.]ourdomain.com/[Home/]Products/old-product-name/page.aspx
to
https://ourdomain.com/new-product-name/
(optional and variable parts are in square and curly brackets).
The first 3 main things I implemented with URL Rewrite rules are the followings:
<rule name="Redirect to HTTPS">
<match url=".*" />
<conditions>
<add input="{HTTPS}" pattern="off" ignoreCase="true" />
</conditions>
<action type="Redirect" url="https://{HTTP_HOST}{REQUEST_URI}" redirectType="Permanent" />
</rule>
<rule name="Canonical Host Name">
<match url="(.*)" />
<conditions>
<add input="{HTTP_HOST}" negate="true" pattern="^ourdomain\.com$" />
</conditions>
<action type="Redirect" url="https://ourdomain.com/{R:1}" redirectType="Permanent" />
</rule>
<rule name="Default Page">
<match url="(.*)default.aspx" />
<conditions>
<add input="{REQUEST_URI}" negate="true" pattern="-default.aspx$" />
</conditions>
<action type="Redirect" url="{R:1}" redirectType="Permanent" />
</rule>
These rules allow to redirect requests like http://www.ourdomain.com/product-name/default.aspx to https://ourdomain.com/product-name.
However, the browser developer tools report that this conversion causes 301 redirects. I tried to find a solution of this redirect chain problem in the Internet and found this post. After reading it, I managed to recode my rules to have just one final 301 redirect with URL rewriting:
<rule name="Redirect to HTTPS">
<match url=".*" />
<conditions>
<add input="{HTTPS}" pattern="off" ignoreCase="true" />
</conditions>
<action type="Rewrite" url="_{REQUEST_URI}" redirectType="Permanent" />
</rule>
<rule name="Canonical Host Name">
<match url="(.*)" />
<conditions>
<add input="{HTTP_HOST}" negate="true" pattern="^ourdomain\.com$" />
</conditions>
<action type="Rewrite" url="_{R:1}" redirectType="Permanent" />
</rule>
<rule name="Default Page">
<match url="(.*)default.aspx" />
<conditions>
<add input="{REQUEST_URI}" negate="true" pattern="-default.aspx$" />
</conditions>
<action type="Rewrite" url="_{R:1}" redirectType="Permanent" />
</rule>
<rule name="FINAL REDIRECT" stopProcessing="true">
<match url="^(_+)(.*)" />
<conditions logicalGrouping="MatchAll" trackAllCaptures="false">
<add input="{HTTP_METHOD}" pattern="GET" />
</conditions>
<action type="Redirect" url="https://ourdomain.com{R:2}" />
</rule>
However, this approach looks non-natural. It makes hard adding new rules because of these workarounds with the underscore character. And maybe, such several rewrite operations for one request may impact on the website performance.
Is there another, more elegant solution, of the 301 redirect chain problem for the URL Rewrite module?
This is not a limitation of IIS Url Rewrite, but the way the web works. A redirection sends a header to the browser telling it that it should navigate to another place. If you have 3 rules that apply to the same original request, and the 3 apply a redirection, then you'll always get 3 redirections no matter how you do it: IIS Url Rewrite, Apache .htaccess or your own custom code.
The solution you've implemented is a "patch" to change several redirections into internal rewrites in the server and a final "catch" of those special rewrites to transform them into a unique redirection at the end (BTW, if you have any real page that strats with _ you won't be able to access it with this extra rule). That's not bad and won't affect your performance, but it's ugly.
I'm not a SEO expert but I think the 301 chaining thing to reach a final similar URL won't hurt your SEO at all in recent times, if that's what worries you (read the final part specially). And being 301 redirects they will affect only the first visit of your users, so probably won't hurt your loading times or conversions either anyway.
However, if you want to avoid that, try to make a single rule for your purpose, doing all the transformations at once. In your case, you want to transform this:
{http|https}://[www.]ourdomain.com/[Home/]Products/old-product-name/page.aspx
(I guess /Home/ can be present sometimes or not)
into this:
https://ourdomain.com/new-product-name/
Then you can use this single rule:
<rule name="New URLs!!" stopProcessing="true">
<match url="^(Home/){0,1}Products/(.+?/).+.aspx" />
<conditions logicalGrouping="MatchAny">
<add input="{HTTPS}" pattern="off" ignoreCase="true" />
<add input="{HTTP_HOST}" negate="true" pattern="^ourdomain\.com$" />
</conditions>
<action type="Redirect" url="https://ourdomain.com/{R:2}" redirectType="Permanent" />
</rule>
and you will transform everything with a single rule (so, just one redirect). The regular expression in the match URL part will identify this specific kind of URL (old product URLs) and the conditions (matching any of them) will take care of the HTTPs and domain change. The stopProcessing="true" will keep other rules to act, and you'll have this specific kind of URLs under control.
Please note that I've not tested this rule and maybe it has minor problems. But you get the idea...
You'll need extra rules after this one to take care of other less-specific URLs, such as your general HTTP to HTTPS or canonical domain rules. But in the case you want to resolve, this will achieve what you want in a single step.

IIS Redirect HTTP to HTTPS and WWW to non-WWW

On IIS 10 with URL Rewrite Module 2.0 I need 2 rules
1) HTTP to HTTPS
2) WWW to non-WWW
First one created by Blank rule template.
For second one I use Canonical domain name template.
In my web.config rules likes like this:
<rewrite>
<rules>
<rule name="ForceHttps" stopProcessing="true">
<match url="(.*)" />
<conditions logicalGrouping="MatchAll" trackAllCaptures="false">
<add input="{HTTPS}" pattern="^OFF$" />
</conditions>
<action type="Redirect" url="https://{HTTP_HOST}/{R:1}" />
</rule>
<rule name="CanonicalHostNameRule1" stopProcessing="true">
<match url="(.*)" />
<conditions logicalGrouping="MatchAll" trackAllCaptures="false">
<add input="{HTTP_HOST}" pattern="^cooltechunder\.com$" negate="true" />
</conditions>
<action type="Redirect" url="https://cooltechunder.com/{R:1}" />
</rule>
</rules>
</rewrite>
All cases works fine expect one starting with: http://www.
See this image for results I have:
https://i.imgur.com/h2l3Yw6.png
You wrote stopProcessing="true".
This means that, if the rule matches, subsequent rules will be skipped.
From the documentation:
A rule may have the StopProcessing flag turned on. When the rule action is performed (i.e. the rule matched) and this flag is turned on, it means that no more subsequent rules will be processed and the request will be passed to the IIS request pipeline. By default, this flag is turned off.
It seems to me that this is the situation you are describing that you did not want.
So, remove it.
Ok, My problem was different and related to bindings.
I have to specify 'Host Name' in bindings, as specific ports used by other websites also
And I forgot to add 'www' versions of bindings also.
Now my bindings looks like this: https://i.imgur.com/Lhdv4nS.jpg
Also I have changed rewrite code to more compact one:
<rewrite>
<rules>
<rule name="Https and non-www">
<match url="(.*)" />
<conditions logicalGrouping="MatchAny">
<add input="{HTTPS}" pattern="^OFF$" />
<add input="{HTTP_HOST}" pattern="^cooltechunder\.com$" negate="true" />
</conditions>
<action type="Redirect" url="https://cooltechunder.com/{R:1}" />
</rule>
</rules>
</rewrite>

Redirect rule http to https not working when using full url

My azure cloud service has both http and https enabled in config files.
I tried adding this rule in my web.config
<rule name="RedirectHTTPToHTTPS" stopProcessing="true">
<match url="(.*)" ignoreCase="true" />
<conditions>
<add input="{HTTPS}" pattern="^OFF$" ignoreCase="true" />
</conditions>
<action type="Redirect" url="https://{HTTP_HOST}/{R:1}" redirectType="Permanent" />
</rule>
if I use http://mysite.kom ,it is correctly redirecting to https://mysite.kom
But if I type http://mysite.kom/other/default.aspx it is redirecting to http://mysite.kom/other/default.aspx instead of https://mysite.kom/other/default.aspx
I added GlobalFilters.Filters.Add(new RequireHttpsAttribute()); in my application_start event.But still "http://mysite.kom/other/default.aspx" is not getting redirected to "https://mysite.kom/other/default.aspx"
I tried all the similar questions in stackoverflow.I even moved the this rule to top of my rules config. Any suggestions to make this working
To resolve this , I added
if (!HttpContext.Current.Request.IsSecureConnection && !HttpContext.Current.Request.Url.Host.Contains("localhost"))
{
Response.Redirect("https://" + Request.ServerVariables["HTTP_HOST"]
+ HttpContext.Current.Request.RawUrl);
}
to Application_BeginRequest event inside my global.asax.cs file
Here is what I use:
<rewrite>
<rules>
<rule name="redirect HTTP to HTTPS" enabled="true" stopProcessing="true">
<match url="(.*)" />
<conditions>
<add input="{HTTPS}" pattern="off" ignoreCase="true" />
<add input="{WARMUP_REQUEST}" pattern="1" negate="true" />
</conditions>
<action type="Redirect" url="https://{HTTP_HOST}/{R:1}" appendQueryString="true" redirectType="Permanent" />
</rule>
</rules>
</rewrite>
While you aren't preserving the query string, it still seems like you have everything necessary to get http->https redirection. That makes me wonder if browser caching is causing you problems? I have had the issue before where I didn't think it was working because I hit the site before enabling http->https redirection and it turned out to be my browser serving up the page from cache.
I wrapped this in a site extension, and it uses the above rewrite rule, so I know it works:
http://www.siteextensions.net/packages/RedirectHttpToHttps/

IIS rewrite rule to redirect https to http not working

There's lots of questions here about redirecting http to https so I figured it would be easy to reverse the process. However, everything I've tried hasn't worked.
I'm trying to combine the rule with my canonical host name rule (it's the first rule, at the top of the rewrite rules):
<rule name="CanonicalHostName" stopProcessing="true">
<match url="(.*)" />
<conditions logicalGrouping="MatchAny">
<add input="{HTTPS}" pattern="^ON$" />
<add input="{HTTP_HOST}" negate="true" pattern="^www\.example\.com|example-staging\.azurewebsites\.net$" />
</conditions>
<action type="Redirect" url="http://www.example.com/{R:1}" redirectType="Permanent" />
</rule>
The site is hosted on Azure and DNS is with CloudFlare if that makes any difference, I'm sure it shouldn't.
Any ideas what I'm doing wrong / might be preventing the https to http part of the rule working? (the host name part works fine)
CloudFlare
It seems the reason you cannot redirect away from SSL is because you are using CloudFlare. CloudFlare at a minimum uses flexible SSL. This means that the end user, browser shows the SSL lock but your server doesn't need SSL. See documentation here: https://www.cloudflare.com/ssl
Without CloudFlare the following example should work.
No CloudFlare
The following rule should work. You could still add your negate in if you want.
<rule name="HTTPS to HTTP redirect" stopProcessing="true">
<match url="(.*)" />
<conditions>
<add input="{HTTPS}" pattern="on" ignoreCase="true" />
</conditions>
<action type="Redirect" redirectType="Found" url="http://{HTTP_HOST}/{R:1}" />
</rule>
Full rewrite section for my working demo site.
<rewrite>
<rules>
<rule name="CanonicalHostNameRule1">
<match url="(.*)" />
<conditions>
<add input="{HTTP_HOST}" pattern="^www\.ashleymedway\.com$" negate="true" />
</conditions>
<action type="Redirect" url="http://www.ashleymedway.com/{R:1}" />
</rule>
<rule name="HTTPS to HTTP redirect" stopProcessing="true">
<match url="(.*)" />
<conditions>
<add input="{HTTPS}" pattern="on" />
</conditions>
<action type="Redirect" url="http://{HTTP_HOST}/{R:1}" redirectType="Found" />
</rule>
</rules>
</rewrite>
Your redirect is still http:
url="http://www.example.com/{R:1}"
You can follow these instructions: Click Here
Additional information: Here

Rewriting URLs from https:// to http:// in IIS7

I'm trying to rewrite urls from the form:
https://example.com/about
to the form
http://example.com/about
using IIS7 URL rewriting:
<!-- http:// to https:// rule -->
<rule name="ForceHttpsBilling" stopProcessing="true">
<match url="(.*)billing/(.*)" ignoreCase="true" />
<conditions>
<add input="{HTTPS}" pattern="off" ignoreCase="false" />
</conditions>
<action type="Redirect" redirectType="Found" url="https://{HTTP_HOST}{REQUEST_URI}" />
</rule>
<!-- https:// to http:// rule -->
<rule name="ForceNonHttps" stopProcessing="true">
<match url="(.*)billing/(.*)" ignoreCase="true" negate="true" />
<conditions>
<add input="{SERVER_PORT}" pattern="^443$" />
</conditions>
<action type="Redirect" redirectType="Found" url="http://{HTTP_HOST}{REQUEST_URI}" />
</rule>
I'm at a loss; I've been browsing the web for examples and trying every syntax I can think of. The rewrite rules I specify simply don't appear to work at all for any https requests, as if all the https:// requests are flat out invisible to the rewrite engine.
rules work fine; see answer below.
Turns out that I had port :443 bound to a different website!
The above rewrite rules work fine for http:// to https:// rewriting and vice-versa -- though there might be more optimal or simple ways to do it.
Leaving this question here for future voyagers to find, as I didn't see many good examples of the https:// to http:// rewriting scenario on the web.
This post is a little old, but I wanted to answer. I am using ASP.Net MVC3, and Fabio's answer above didn't work for me. The easiest solution I came up with to handle the https redirect to http, while still allowing valid https pages to request secure content was just to add Whitelist rules above my https/http redirects:
<rule name="WhiteList - content folder" stopProcessing="true">
<match url="^content/"/>
<conditions logicalGrouping="MatchAll" trackAllCaptures="false"/>
<action type="None"/>
</rule>
<rule name="Redirect to HTTPS" stopProcessing="true">
<match url="(.*)billing/(.*)" ignoreCase="true" />
<conditions>
<add input="{HTTPS}" pattern="^OFF$" />
</conditions>
<action type="Redirect" url="https://{HTTP_HOST}/billing/" redirectType="SeeOther" />
</rule>
<rule name="ForceNonHttps" stopProcessing="true">
<match url="(.*)billing/(.*)" ignoreCase="true" negate="true" />
<conditions>
<add input="{SERVER_PORT}" pattern="^443$" />
</conditions>
<action type="Redirect" redirectType="Found" url="http://{HTTP_HOST}{REQUEST_URI}" />
</rule>
please first consider binding https to your website for making below redirect module to work is essential (so bind your web app with a self-signed or valid certificate)
final part in web.config to redirect https to http:
<rewrite>
<rules>
<rule name="Force NonHTTPS" stopProcessing="true">
<match url="(.*)" />
<conditions>
<add input="{HTTPS}" pattern="on" />
</conditions>
<action type="Redirect" url="http://{HTTP_HOST}/{REQUEST_URI}" />
</rule>
</rules>
</rewrite>
if you need the equivalent IIS GUI in rewrite module see below image
source: look tech-net for more detail and step by step guide.
Your solution work, but the problem is: your second instruction kill first instruction for any links is not (.)billing/(.), including your css, js, and images.
You can use this https to http rule:
<rule name="HTTPS to HTTP redirect" stopProcessing="true">
<match url="(.*)" />
<conditions>
<add input="{RequiresSSL:{R:1}}" pattern="(.+)" negate="true" />
<add input="{HTTPS}" pattern="on" ignoreCase="true" />
<add input="{REQUEST_URI}" pattern="^(.+)\.(?!aspx)" negate="true" />
</conditions>
<action type="Redirect" redirectType="Found" url="http://{HTTP_HOST}/{R:1}" />
</rule>

Resources