IIS Rewrite rule - ignore for localhost - regex

I have the following rule which is working well for redirecting my www requests to the root.
However I can't seem to turn it off for localhost. Here is what I have now:
<rule name="CanonicalHostNameRule1">
<match url="(.*)" />
<conditions>
<add input="{HTTP_HOST}" pattern="^example\.com$" negate="true" />
</conditions>
<action type="Redirect" url="https://example.com/{R:1}" />
</rule>
I've tried many things including things like:
<rule name="CanonicalHostNameRule1">
<match url="(.*)" />
<conditions>
<add input="{HTTP_HOST}" pattern="^localhost$" negate="true" />
<add input="{HTTP_HOST}" pattern="^example\.com$" negate="true" />
</conditions>
<action type="Redirect" url="https://example.com/{R:1}" />
</rule>
Could you help? Regexes are my weakness alas

How about using a condition to only match requests that start with www. instead of trying to negate when you don't want the rule to apply? This avoids the need to negate localhost because localhost never matches in the conditions:
<rule name="Strip WWW" stopProcessing="true">
<match url="(.*)" />
<conditions>
<add input="{HTTP_HOST}" pattern="^www\.(.*)" />
</conditions>
<action type="Redirect" url="https://{C:1}/{URL}" />
</rule>
However, your example of the rule you tried (your second code block) also works for me in testing with IIS on a Windows 10 VM. I can browse to localhost without a redirect. Perhaps there is another issue here.

I would not mix the rules of different hosting environments; localhost (for local development) and www, your live environment.
If you keep them separate, you don't have to enable and disable rules depending on the environment.
The rules section has a configSource attribute via which you can point to an other separate file, eg. RewriteRules.config.
Doing so, web.config will look like here below.
<configuration>
<!-- Other settings go here. -->
<system.webServer>
<!-- other settings go here --->
<rewrite>
<rules configSource="RewriteRules.config">
</rewrite>
</system.webServer>
</configuration>
The RewriteRules.config file contains the rules.
<rules>
<rule name="CanonicalHostNameRule1">
<!-- Rule details go here -->
</rule>
</rules>
You make a separte version of this RewriteRules.configfile per environment, containing only the appropriate rules and deploy it to the concerned webserver.
This has many benefits.
Only the rules for the concerned environment are being evaluated, which is better for performance.
It is more flexible if you have other environments like QA (http://qa. ...) and dev (http://dev. ...).
You don't have to worry (and test) whether the rules of one environment will interfere with the ones of an other one, here: local vs live.
The deployment of the RewriteRules.config file can be included in a deployment automation.

Related

IIS Rewrite - redirect site to new domain capturing the language embedded in the URL

I am trying to write a regex to redirect the URL to a new domain. I wrote IIS Rewrite rule for this:
<rule name="Redirect to new domain" stopProcessing="true">
<match url="^(.*)" />
<conditions>
<add input="{HTTP_HOST}" pattern="^(www\.)?my-www-en\.sites\.company\.net(\/([a-zA-Z]{2,3}-[a-zA-Z]{2,3}|en)\/?)?(.*$)" />
</conditions>
<action type="Redirect" redirectType="Permanent" url="https://my-new-domain.com/en-us/{C:4}" appendQueryString="true" />
</rule>
It works fine when the language is not added to the initial URL, however, some of the pages have the language added after the domain which results in double language appearance in the end URL.
So basically I would like to redirect things like:
my-www-en.sites.company.net/some-page/another/page/
www.my-www-en.sites.company.net/some-page/another/page/
my-www-en.sites.company.net/de-de/some-page/another/page/
www.my-www-en.sites.company.net/de-de/some-page/another/page/
my-www-en.sites.company.net/en/some-page/another/page/
to redirect to:
https://my-new-domain.com/en-us/some-page/another/page/
My current regex does not capture these groups correctly (even when it does while testing the regex in IIS rewrite) and I struggle to make it work. Right now everything gets redirected to the homepage instead to particular websites. Could you please help?
Please try this rule. The regular expressions can match all urls above.
<rule name="test">
<match url=".*" />
<conditions>
<add input="{HTTP_HOST}" pattern="^(www\.)?my-www-en\.sites\.company\.net$" />
<add input="{REQUEST_URI}" pattern="(/.*)?(/some-page/another/page/)" />
</conditions>
<action type="Rewrite" url="https://my-new-domain.com/en-us{C:2}" />
You can change rewrite to redirect.

What is wrong with this redirect rule?

I'm using the code below to create a redirect rule in my web.config file in the root directory of a site hosted in a Windows server:
<rewrite>
<rules>
<clear />
<rule name="Redirect https" enabled="true" stopProcessing="true" patternSyntax="ECMAScript">
<match url=".*cashpreview\\.com\\.br.*" ignoreCase ="true" />
<conditions>
<add input="{HTTPS}" pattern="off" ignoreCase="true" />
</conditions>
<action type="Redirect" url="https://{HTTP_HOST}{REQUEST_URI}" redirectType="Permanent" />
</rule>
</rules>
</rewrite>
The rule works for the address http://www.cashpreview.com.br/cashpreview/cashbr.htm but not for
http://www.cashpreview.com.br/cashpreview/janelas.htm . If I try to access the first address, the "https" replace the "http", but the same doesn't occurs for the second address. I need to write the domain in the regular expression because I have multiple domains sharing the same web directory and only this has SSL installed for it. Does somebody knows what could be causing this strange behaviour of the rule?
Now, I've discovered my errors. I was not aware that the parameter url of the match element contains only the part of the url relative to the directory where the web.config file is located. So, the domain never is part of the url. As I have multiple domains sharing the same web directory, I added a new condition checking the {HTTP_HOST} for the only domain for which I've installed SSL. As I have asp files in the site and I used {REQUEST_URI} that include de querystring, I turned off the appendquerystring attribute. My code now is like below:
<rewrite>
<rules>
<clear />
<rule name="Redirect https" enabled="true" stopProcessing="true" patternSyntax="ECMAScript">
<match url=".*" ignoreCase ="true"/>
<conditions logicalGrouping="MatchAll">
<add input="{HTTPS}" pattern="off" ignoreCase="true" />
<add input="{HTTP_HOST}" pattern=".*cashpreview\.com\.br" ignoreCase="true" />
</conditions>
<action type="Redirect" url="https://{HTTP_HOST}{REQUEST_URI}" redirectType="Permanent" appendQueryString="false"/>
</rule>
</rules>
</rewrite>
That case where sometimes the things go right was only for data cached in my browser. Using a proxy, that case didn't worked the way I was doing before too.

IIS rewrite rule not working in live environment

I have 4 servers in azure, 3 are load balanced and the 4th is for CMS purposes only.
SSL certificate has been added for the main website, but not for the sobdomain that the CMS is on.
I wrote a rule that should find any url that doesnt contain "backoffice" and match any other page to change it to https.
This works on regexr.com but for some reason doesnt work
<rewrite>
<rules>
<rule name="http to https" stopProcessing="true">
<match url="(https?:\/\/(?!backoffice).*)" />
<conditions>
<add input="{HTTPS}" pattern="^OFF$" />
</conditions>
<action type="Redirect" url="https://www.WEBSITENAME.com{R:1}" />
</rule>
</rules>
</rewrite>
Url Rewriting 2.1 is installed on all 4 servers and i have created a load balance set in azure for https.
going to https manually works fine (along with loadbalancing).
Additional information:
I've tried many rules, including the existing answer. I can see things happening, like assets being brought in as https, but the page itself does not redirect.
There are 2 load balance sets, one for port 80 and the other for port 443. I don't know if this is corect, or could be a potential cause in the redirect not happening.
Your rule should be like that:
<rule name="http to https" stopProcessing="true">
<match url=".*" />
<conditions>
<add input="{HTTPS}" pattern="^OFF$" />
<add input="{REQUEST_URI}" pattern="/backoffice" negate="true" />
</conditions>
<action type="Redirect" url="https://www.WEBSITENAME.com{R:0}" />
</rule>
This rule will exclude requests with /backoffice path.
Also for issue of mixing content you need to fix your paths for css/js/images to relatives. Example:
<img src="/path/to/your/image.jpg"/>
Another way to fix mixed content is create outbound rule, which will change your output HTML (replace http: to https:):
<rewrite>
...
<outboundRules>
<rule name="Rewrite external references to use HTTPS" preCondition="IsHTML">
<match filterByTags="Script, Link, Img, CustomTags" customTags="HTML5Tags" pattern="^http://(.*)$" />
<action type="Rewrite" value="https://{R:1}" />
</rule>
<preConditions>
<preCondition name="IsHTML">
<add input="{RESPONSE_CONTENT_TYPE}" pattern="^text/html" />
</preCondition>
</preConditions>
<customTags>
<tags name="HTML5Tags">
<tag name="Video" attribute="src" />
</tags>
</customTags>
</outboundRules>
</rewrite>
Using the previous answer as a starting point, i made a few minor changes, to use HTTP_HOST rather than REQUEST_URI for the pattern negation and it works.
<system.webServer>
<rewrite xdt:Transform="InsertIfMissing">
<rules>
<rule name="http to https" stopProcessing="true">
<match url=".*" />
<conditions>
<add input="{HTTPS}" pattern="^OFF$" />
<add input="{HTTP_HOST}" pattern="^backoffice\.WEBSITENAME\.com$" negate="true" />
</conditions>
<action type="Redirect" url="https://www.WEBSITENAME.com/{R:0}" />
</rule>
</rules>
</rewrite>
</system.webServer>

IIS ARR rules not working as expected in adding trailing slashes to my applications

I have a pool of applications that I want to run under a ARR server that should serve as a router for all my applications.
I have defined a set of rules that should be applied in waterfall, but something is not working the proper way.
The first rule should handle the trailing slashes, the other rules should map my applications to resolve for my internal DNS server with rewrite URL, but the problem seems to happen during the first rule.
The default behaviour is that, if I try to launch my application with http://myapp will return 404 code, if I try to run it by adding the slash (http://www.myapp/ ) everything works fine. So basically my rule should check for URL patterns without the slash: if the resource is a directory it should add the slash at the end of the Url.
So the pattern to catch the url is the following regular expression:
.*[^/]$
This should catch url without / at the end and I successfully tested it.
For every url that matches the regexp, I should check if it's a directory, and in the case I should set the trailing slash, so:
{REQUEST_FILE} -> Is a directory
But this doesn't work. I also tried to add the following rule with no success:
{REQUEST_FILE} -> Is not a file
The rule to apply is the following:
Redirect to (rewrite leads to same behaviour, too):
{R:O}/
It seems not to add the / to my urls and I don't know how to check which steps fail to succeed. The next rules basically follow this pattern:
mywebapp/* redirect to www.mydnsappaddress/{R:1}
EDIT: I add the web.config sample to show you the textual version of the rules.
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<rewrite>
<rules>
<clear />
<rule name="Trailing Slash" enabled="false" stopProcessing="true">
<match url=".*[^/]$" />
<conditions logicalGrouping="MatchAll" trackAllCaptures="false">
<add input="{REQUEST_FILENAME}" matchType="IsFile" />
</conditions>
<action type="Redirect" url="{R:0}/" />
</rule>
<rule name="app1" enabled="false" patternSyntax="Wildcard">
<match url="sites/doc/*" />
<conditions logicalGrouping="MatchAll" trackAllCaptures="false" />
<action type="Rewrite" url="http://mypersonaldnsaddress/{R:0}" />
</rule>
<rule name="ASTCO portale NWS" enabled="true" patternSyntax="Wildcard">
<match url="portale/*" />
<conditions logicalGrouping="MatchAll" trackAllCaptures="false" />
<action type="Rewrite" url="http://mypersonaldnsaddress/{R:0/{R:0}" />
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>
I have to ask the obvious: does your example deliberately have enabled set to false?
I was able to make this work exactly as you desire: if the directory exists, add a slash at the end, if it doesn't, don't.
<rule name="Trailing Slash" enabled="true" stopProcessing="true">
<match url=".*[^/]$" />
<conditions logicalGrouping="MatchAll" trackAllCaptures="false">
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" />
</conditions>
<action type="Redirect" url="{R:0}/" />
</rule>

URL Rewrite - stop https for staging guid url on Azure (IIS)

I have this rewrite rule in web.config on our Azure app to ensure the users always use HTTPS:
<rule name="HTTP to HTTPS redirect"
stopProcessing="true">
<match url="(.*)" />
<conditions>
<add input="{HTTPS}"
pattern="off" />
<add input="{REQUEST_URI}"
pattern="^clientaccesspolicy\.xml$"
negate="true" />
<add input="{REQUEST_URI}"
pattern="^crossdomain\.xml$"
negate="true" />
</conditions>
<action type="Redirect"
redirectType="Found"
url="https://{HTTP_HOST}/{R:1}" />
</rule>
It works fine. The users always hit the site using a subdomain of our company URL and we have a wildcard certificate.
But when the app is staging I would like to use it without https (but still not allow http acccess to the standard cloudapp subdomain).
so for example this would work over http:
http://f9eccd6a9a044270b5ce97ae614c9ee1.cloudapp.net
But this wouldn't:
http://myazuresubdomain.cloudapp.net
My Regex skills are minimal and my url rewrite skils are limited to copying the above from SO. So could someone help me with the rule that will help me acheive the above? Perhaps a negate for a url that has exactly 32 chracters then .cloudapp.net?
Thanks
Mark
The following rule should match what you're after. Placing it first will skip the https redirect due to the 'stopProcessing' attribute.
<rule name="Staging CloudApp" stopProcessing="true">
<match url=".*" />
<conditions logicalGrouping="MatchAll" trackAllCaptures="false">
<add input="{HTTP_HOST}" pattern="([0-9a-f]{32})\.cloudapp\.net" />
</conditions>
<action type="None" />
</rule>