Trailing slash Umbraco and HTTPs - asp.net

I have an Umbraco site that sits behind a Netscaler. All requests are translated from http to https (via Netscaler) and a trailing slash is appended using IIS rewrites. The IIS re-write rule is causing a HTTPS request (without a trailing slash) to insert an additional request with a Status of 302. Essentially:
https://example.com/news (Status 301)
http://example.com/news/ (Status 302)
https://example.com/news/ (Status 200)
Ideally I would like one 301 Redirect and then a 200 - I need to remove the temporary redirect
The IIS rewrite rule to add trailing slashes:
<rule name="Add trailing slash" stopProcessing="true">
<match url="(.*[^/])$" ignoreCase="true" />
<conditions>
<add input="{REQUEST_METHOD}" pattern="POST" negate="true" />
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
<add input="{REQUEST_URI}" pattern="^/umbraco/" negate="true" />
<add input="{URL}" pattern="^.*\.(asp|aspx|axd|asmx|css|htc|js|jpg|jpeg|png|gif|mp3|ico|pdf|txt|htm|html|php|xml)$" negate="true" ignoreCase="true" />
<add input="{URL}" pattern="/Base" negate="true" />
<add input="{URL}" pattern="cdv=1" negate="true" />
</conditions>
<action type="Redirect" redirectType="Permanent" url="{R:1}/" />
</rule>
I have already implemented in the umbracoSettings.config file
{addTrailingSlash}true{/addTrailingSlash}
I have also tried the rewrite rule
<rule name="HTTP Redirect to HTTPS" enabled="true" patternSyntax="ECMAScript" 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>
But this causes an infinite loop of 301's and the page dies
Running out of idea's

Sorted it.
<action type="Redirect" redirectType="Permanent" url="{R:1}/" />
Is not enough even though the redirect is Permanent the protocol is standard port 80. The action type need to updated to:
<action type="Redirect" url="https://{HTTP_HOST}/{R:1}/" redirectType="Permanent" />
You need to specify https complete with the host and the {R:1}/ in the url attribute

Related

Web.Config uppercase to lowercase Redirection - Losing HTTPS schema

I have the following rule to redirect an upper case URL to a lower case URL
But what I see is the HTTPS URL is getting redirected to HTTP URL. So, https://example.com/UPPERCASE is getting redirected to http://example.com/uppercase. I want the redirect to happen to https URL i..e, https://example.com/uppercase. Please suggest.
<rule name="LowerCaseRule" stopProcessing="true">
<match url="[A-Z]" ignoreCase="false" />
<action type="Redirect" url="{ToLower:{URL}}" />
<conditions>
<add input="{REQUEST_URI}" pattern="^.*/install" negate="true" />
<add input="{REQUEST_URI}" pattern="^.*/media" negate="true" />
<add input="{REQUEST_URI}" pattern="^.*/App_Plugins" negate="true" />
<add input="{REQUEST_URI}" pattern="^.*/css" negate="true" />
<add input="{REQUEST_URI}" pattern="^.*/scripts" negate="true" />
</conditions>
</rule>
The url attribute does not include the schema, you need to explicitly specify the schema in the redirect:
<action type="Redirect" url="https://{ToLower:{HTTP_HOST}}{ToLower:{REQUEST_URI}}" />
This will solve your problem.

Redirect to different domain while preserve subdomains and query parameters and also enforce https using web.config

Using the Web.config only, I need to redirect all traffic to a new domain, yet also:
1) preserve subdomains
2) preserve query parameters
3) if "http" and not "https" change to "https" while doing the above
I can easily handle enforcing HTTPS, and I have seen many references to redirects for domains, but have not found any that preserve the subdomains while changing to the root domain.
<rewrite>
<rules>
<rule name="Redirect HTTP to HTTPS" stopProcessing="true">
<match url="^(.*)$" />
<conditions trackAllCaptures="true">
<add input="{HTTPS}" pattern="^OFF$" />
<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" />
</conditions>
<action type="Redirect" url="https://{HTTP_HOST}/{R:1}" redirectType="SeeOther" />
</rule>
</rules>
</rewrite>
'The above works to change http to https, but does not help with the need to change the domain. I have also seen this below which almost works:'
<rule name="redirect" enabled="true">
<match url="(.*)" />
<conditions>
<add input="{HTTP_HOST}" negate="false" pattern="^(.*)\.foo\.com" />
</conditions>
<action type="Redirect" url="https://{C:1}.bar.com/{R:1}" appendQueryString="true" redirectType="Permanent" />
</rule>
...but removes the subdomain:
http://x.foo.com > https://.bar.com
Examples of what it needs to do:
http://x.foo.com > https://x.bar.com
https://y.foo.com > https://y.bar.com
https://x.foo.com/blah.aspx?param=blue > https://x.bar.com/blah.aspx?param=blue
http://y.foo.com/blah.aspx?param=blue > https://y.bar.com/blah.aspx?param=blue
Okay, I have come up with the following solution that does exactly what I have needed (see above requirements). I did this by adding two independent rule blocks: one to ensure HTTPS, and the other to do a redirect to the other domain if necessary. I sense that this does double the traffic if the visit needs both 1) HTTP to HTTPS and 2) direct to the new domain (from *.foo.com > *.bar.com) but at least it works. Not sure if it could be tweaked into one rule to save hits?
<rewrite>
<rules>
<rule name="Redirect HTTP to HTTPS" stopProcessing="true">
<match url="^(.*)$" />
<conditions trackAllCaptures="true">
<add input="{HTTPS}" pattern="^OFF$" />
<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" />
</conditions>
<action type="Redirect" url="https://{HTTP_HOST}/{R:1}" redirectType="SeeOther"/>
</rule>
<rule name="Redirect to new domain" enabled="true">
<match url="(.*)$" />
<conditions trackAllCaptures="true">
<add input="{HTTP_HOST}" negate="false" pattern="^(.*)\.foo\.com" />
</conditions>
<action type="Redirect" url="https://{C:1}.bar.com/{R:1}" appendQueryString="true" redirectType="Permanent" />
</rule>
</rules>
</rewrite>

URL Rewrite in IIS 7 causes redirect loop

I have tried various methods found on the web (including some SO answers) for getting URL rewrite in IIS 7 to work so that I can turn mysite.com/somepage.aspx into mysite.com/somepage, for example. The last thing I've tried is the video at this link: https://www.youtube.com/watch?v=bBNJE7XA1m0. After applying these changes in IIS, I now can request mysite.com/somepage and get to mysite.com/somepage.aspx with the .aspx removed in the address bar. Partial success.
When I try to directly request mysite.com/somepage.aspx, however, I get into a redirect loop. I am hoping there is some simple mistake in my settings. Here is the web.config section created by making changes in IIS:
<rewrite>
<rules>
<rule name="HideAspxExtension">
<match url="^(.*)$" />
<conditions logicalGrouping="MatchAny">
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
<add input="{REQUEST_FILENAME}.aspx" matchType="IsFile" />
</conditions>
<action type="Rewrite" url="{R:0}.aspx" />
</rule>
<rule name="RedirectingAspxExtension" stopProcessing="true">
<match url="^(.*).aspx$" />
<conditions logicalGrouping="MatchAny">
<add input="{URL}" pattern="^(.*).aspx$" />
</conditions>
<action type="Redirect" url="{R:1}" />
</rule>
</rules>
</rewrite>
I have tried to apply this setting to multiple applications and I get the same results. What I do not have is another server to test on.
These are rules I've used before:
<rule name="StripAspx">
<match url="^(.+)\.aspx$" />
<action type="Redirect" url="{R:1}" redirectType="Permanent" />
</rule>
<!-- Rewrite the .aspx for internal processing-->
<rule name="RewriteASPX" stopProcessing="true">
<match url="(.*)" />
<conditions logicalGrouping="MatchAll">
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
</conditions>
<action type="Rewrite" url="{R:1}.aspx" />
</rule>
The main differences I can see are:
These have the removal of the .aspx first (in rewrite rules, order matters). This also means that in these rules the stopProcessing directive is on the rewrite to .aspx, not the redirect away from it.
These don't have <add input="{REQUEST_FILENAME}.aspx" matchType="IsFile" />

IIS Rewrite Rule - How to include root documents

I have a simple IIS rule to redirect HTTPS to HTTP:
<rule name="HTTPS" enabled="true" stopProcessing="true">
<match url=".*\.(asp)$" ignoreCase="false" />
<conditions>
<add input="{HTTPS}" pattern="on" />
<add input="{REQUEST_URI}" negate="true" pattern="^/ecards/user*" ignoreCase="true" />
</conditions>
<action type="Redirect" url="http://{HTTP_HOST}/{R:1}" appendQueryString="true" redirectType="Permanent" />
</rule>
The matching url will only work on .asp files, but how can I also get it to work for root directories?
E.g.
example.com
example.com/
example.com/test
example.com/test/
I don't want to just have the match URL as:
<match url="(.*)" />
Because then other non .asp files get rewritten.
One way to include directories in your rule is to exclude everything else.
Assuming that everything else has a file extension (e.g. .php, .css. .js, etc.) you can negate all input that has the . in the path.
I changed your code a bit to make a working demo locally (I don't have HTTPS locally to test so instead of redirecting to HTTP I set it to redirect to About.aspx) and the two rules are:
<rule name="HTTPS" enabled="true" stopProcessing="true">
<match url=".*\.(asp)$" ignoreCase="false" />
<action type="Redirect" url="/About.aspx" appendQueryString="true" redirectType="Permanent" />
</rule>
<rule name="NEWRULE" enabled="true" stopProcessing="true">
<match url="(.*)" />
<conditions>
<add input="{REQUEST_URI}" negate="true" pattern=".*\.(.)$" ignoreCase="true" />
<add input="{REQUEST_URI}" negate="true" pattern="^/About*" ignoreCase="true" />
</conditions>
<action type="Redirect" url="/About.aspx" appendQueryString="true" redirectType="Permanent" />
</rule>
So, based on your original code sample, a new rule that will work for you would be similar to this:
<rule name="IncludeDirectories" enabled="true" stopProcessing="true">
<match url="(.*)" />
<conditions>
<add input="{REQUEST_URI}" negate="true" pattern=".*\.(.)$" ignoreCase="true" />
<add input="{HTTPS}" pattern="on" />
<add input="{REQUEST_URI}" negate="true" pattern="^/ecards/user*" ignoreCase="true" />
</conditions>
<action type="Redirect" url="http://{HTTP_HOST}/{R:1}" appendQueryString="true" redirectType="Permanent" />
</rule>
Note: The above approach is rather aggressive. You could replace this condition:
<add input="{REQUEST_URI}" negate="true" pattern=".*\.(.)$" ignoreCase="true" />
with the following:
<add input="{REQUEST_URI}" negate="true" pattern=".*\.(php|css|js|jpg|gif|png)$" ignoreCase="true" />
Where you exclude specific extensions. You add as many as you want.
Edit: If you want to have specific pages still with HTTPS maybe the following rule will be helpful (haven't tested it though). The previous rule sends to HTTP all URLs except those that have /ecards/user where this one sends to HTTPS those that have /ecards/user. I believe there will be no conflict.
<rule name="HTTPS2Admins" enabled="true" stopProcessing="true">
<match url="/ecards/user(.*)" />
<conditions>
<add input="{HTTP}" pattern="on" />
</conditions>
<action type="Redirect" url="https://{HTTP_HOST}/ecards/user{R:1}" appendQueryString="true" redirectType="Permanent" />
</rule>

How to redirect all non-www URLs to https://www. in IIS?

I want to add the proper 301 permanent redirect rule in IIS 8.5. I've added the following rules but it is not working.
<rule name="Redirect top domains with non-www to www" stopProcessing="true">
<match url="(.*)" />
<conditions logicalGrouping="MatchAll" trackAllCaptures="false">
<add input="{HTTP_HOST}" pattern=".*localhost.*" negate="true" />
<add input="{HTTP_HOST}" pattern=".*stage\..*" negate="true" />
<add input="{HTTP_HOST}" pattern=".*dev\..*" negate="true" />
<add input="{HTTP_HOST}" pattern="^(http:\/\/){0,1}(www\.){0,1}([^\.]+)\.([^\.]+)$" ignoreCase="true" />
</conditions>
<action type="Redirect" url="https://www.{C:3}.{C:4}" redirectType="Permanent" />
</rule>
Conditions
If the URL is in HTTPS and contains "www." then NO redirect. Example: https://www.example.com
If the URL is in HTTP then it should be redirected to HTTPS. Example: http://www.example.com should be redirected to https://www.example.com
If the URL is in HTTPS but does NOT contain "www." then it should be redirected to HTTPS site with "www." prefix. Example: https://example.com should be redirected to https://www.example.com
If the URL neither contains HTTPS nor WWW then redirect to HTTPS URL with "www." prefix. Example: http://example.com should be redirected to https://www.example.com
To summarize, every URL should be in HTTPS and should have "www." prefix.
NOTE: I have installed URL Rewrite Module in IIS.
Can anyone please help me to achieve this?
I managed it by adding two URL rewrite rules in Web.config file:
For redirecting non-www to https://www.{domain}.com/...
Redirecting HTTP to HTTPS
<rule name="Redirect top domains with non-www to www" stopProcessing="true">
<match url="(.*)" />
<conditions logicalGrouping="MatchAll" trackAllCaptures="false">
<add input="{HTTP_HOST}" pattern=".*localhost.*" negate="true" />
<add input="{HTTP_HOST}" pattern=".*stage\..*" negate="true" />
<add input="{HTTP_HOST}" pattern=".*dev\..*" negate="true" />
<add input="{HTTP_HOST}" pattern="^([^\.]+)\.([^\.]+)$" />
</conditions>
<action type="Redirect" url="https://www.{HTTP_HOST}/{R:1}" redirectType="Permanent" />
<serverVariables>
<set name="Redirect" value="false" />
</serverVariables>
</rule>
<rule name="Force HTTPS" enabled="true" stopProcessing="true">
<match url="(.*)" ignoreCase="false" />
<conditions logicalGrouping="MatchAll" trackAllCaptures="false">
<add input="{HTTP_HOST}" pattern=".*localhost.*" negate="true" />
<add input="{HTTP_HOST}" pattern=".*stage\..*" negate="true" />
<add input="{HTTP_HOST}" pattern=".*dev\..*" negate="true" />
<add input="{HTTPS}" pattern="off" />
</conditions>
<action type="Redirect" url="https://{HTTP_HOST}/{R:1}" appendQueryString="true" redirectType="Permanent" />
</rule>
All the conditions with negate="true" are used for exclusion. Hence all URLs which contains "localhost", "stage", and "dev" are excluded from URL rewrite. You can remove these conditions if not required.
Read more about negate attribute at http://www.iis.net/learn/extensions/url-rewrite-module/creating-rewrite-rules-for-the-url-rewrite-module

Resources