Multiple rewriteMaps in IIS7, only one responding - iis-7

I have more than one rewrite map in my site, but only one map seems to be working.
The relevant chunk of the Web.config file reads:
<system.webServer>
<rewrite>
<rewriteMaps configSource="rewriteMaps.config"/>
<rules>
<rule name="Locale redirects">
<match url="^/?[a-z][a-z](-[a-z][a-z])?/?$"/>
<conditions>
<add input="{LocaleRedirects:{REQUEST_URI}}" pattern="(.+)"/>
</conditions>
<action type="Redirect" url="{C:1}" appendQueryString="true"/>
</rule>
<rule name="Short URL redirects">
<match url="^/?[a-z][a-z](-[a-z][a-z])?/?$"/>
<conditions>
<add input="{ShortURLs:{REQUEST_URI}}" pattern="(.+)"/>
</conditions>
<action type="Redirect" url="{C:1}" appendQueryString="true"/>
</rule>
</rules>
</rewrite>
</system.webServer>
My file rewriteMaps.config (with several lines removed for demonstration purposes) reads:
<rewriteMaps>
<rewriteMap name="ShortURLs">
<add key="getstarted" value="/en-us/get-started/"/>
<add key="support" value="/en-us/support/"/>
<add key="terms" value="/en-us/terms-and-conditions/"/>
<add key="getstarted/" value="/en-us/get-started/"/>
<add key="support/" value="/en-us/support/"/>
<add key="terms/" value="/en-us/terms-and-conditions/"/>
</rewriteMap>
<rewriteMap name="LocaleRedirects">
<add key="/jp" value="/ja-JP/"/>
<add key="/jp/" value="/ja-JP/"/>
<add key="/kr" value="/ko-kr/"/>
<add key="/kr/" value="/ko-kr/"/>
</rewriteMap>
</rewriteMaps>
All the locale redirects are working perfectly; none of the short URLs is working, however; they just give a 404 response.
Is there something I'm doing obviously-wrong? Or is there some intricacy to using multiple rewrite maps that I'm missing somehow?

There are few issues here with your Rewrite Rules:
1) For Short URL redirects you are matching string such as /en-gb or /en-gb/ That is why your local redirects are working but not when string is "getstarted"
<rule name="Short URL redirects">
<match url="^/?[a-z][a-z](-[a-z][a-z])?/?$"/>
Should be <match url="(.*)" or if you prefer reg ex as url="^/.*/?" this will match /getstarted or /getstarted/.
2) In your rewritemap you need to specify key as /getstarted instead of just getstarted.
<rewriteMap name="ShortURLs">
<add key="getstarted" value="/en-us/get-started/"/>
Should be:
<rewriteMap name="ShortURLs">
<add key="/getstarted" value="/en-us/get-started/"/>

Related

IIS URL Rewrite except specific site

I have 3 sites (with different domains) which are hosted on one server, but all of them have same source and web.config. Sites 1 and 2 will be stopped and they should redirect to Site 4, but Site 3 will work as now...
I added a RewriteMap where described all pages redirects and a rule which is using that map:
<rewrite>
<rewriteMaps>
<rewriteMap name="My_RewriteMap" defaultValue="localhost/site4/Welcome.aspx">
<add key="/" value="localhost/site4/Welcome.aspx" />
<add key="/default.aspx" value="localhost/site4/Welcome.aspx" />
<add key="localhost/site2" value="localhost/site4/SpecificPage.aspx" />
<add key="/page3.aspx" value="localhost/site4/MyPage.aspx" />
<add key="new-page.aspx" value="localhost/site4/TheNewPage.aspx" />
...
</rewriteMap>
</rewriteMaps>
<rules>
<rule name="Redirect rule1 for My_RewriteMap" stopProcessing="true">
<match url=".*" negate="false" />
<conditions>
<add input="{My_RewriteMap:{REQUEST_URI}}" pattern="(.+)" />
</conditions>
<action type="Redirect" url="{C:1}" appendQueryString="false" />
</rule>
</rules>
</rewrite>
This code works for described pages in Map and for default value (if a specific page doesn't exist in the Map).
But this redirects Site 1, Site 2 and Site 3. I don't want to redirect to for Site3.
Is it possible with Rewrite URL feature?
I tried to edit match value with
<match url="localhost/Site3" negate="true" />
or
<match url="(localhost/Site3).*" negate="true" />
But both didn't work.
Thanks!
I Completed with next changes in conditions:
<conditions trackAllCaptures="true">
<add input="{HTTP_HOST}" pattern="localhost/Site3" negate="true" />
<add input="{My_RewriteMap:{REQUEST_URI}}" pattern="(.+)" />
</conditions>
With the first condition, I say to ignore all requests where Host (in {HTTP_HOST} variable) contains the site's domain: localhost/Site3.
Then, the second condition works for the Map.

IIS Re-write module not working for default document request

I'm trying to use the IIS rewrite module to redirect HTTP to HTTPS for certain areas of my site.
It works mostly. However I've noticed a strange inconsistency if the request uses the default document.
For example...
http://[mydomain]/test_folder/default.aspx
correctly redirects to...
https://[mydomain]/test_folder/default.aspx
However, this URL...
http://[mydomain]/test_folder/
does not redirect.
My re-write rules are defined as follows...
<rewrite>
<rules>
<rule name="Redirect to HTTPS" stopProcessing="true">
<match url="(.*)" />
<conditions>
<add input="{HTTPS}" pattern="^OFF$" />
<add input="{HTTP_HOST}" pattern="^mydomain.com$" ignoreCase="true" />
<add input="{SCRIPT_NAME}" pattern="^/(?:admin|test_).*" ignoreCase="true" />
</conditions>
<action type="Redirect" url="https://{HTTP_HOST}/{R:1}" redirectType="Permanent" />
</rule>
</rules>
</rewrite>
My default documents are defined as follows...
<defaultDocument enabled="true">
<files>
<clear />
<add value="default.asp" />
<add value="default.aspx" />
</files>
</defaultDocument>
It's like having processed the request for the default document, it doesn't bother to process my rewrite rules.
Can anyone suggest what I might be doing wrong, and how to resolve it?
Update: I've been able to work around the problem by removing the rewrite rules, and instead doing the redirection in global.asax. This seems like a slightly hacky way to do it though, so I would prefer to use IIS rewrite if there is a proper solution.
This rule will redirect all requests which stars with admin or test_:
<rule name="redirect to HTTPS" stopProcessing="true">
<match url="^(admin|test_)" />
<conditions>
<add input="{HTTPS}" pattern="^OFF$" />
<add input="{HTTP_HOST}" pattern="^mydomain.com$" ignoreCase="true" />
</conditions>
<action type="Redirect" url="https://{HTTP_HOST}{REQUEST_URI}"/>
</rule>
Example:
http://[mydomain]/test_folder/default.aspx to https://[mydomain]/test_folder/default.aspx
http://[mydomain]/admin/default.aspx to https://[mydomain]/admin/default.aspx
http://[mydomain]/test_folder/ to https://[mydomain]/test_folder/

Redirect single page to another domain

I need to redirect couple old webpages from my IIS to a new domain in a specific order.
For instance :
domain1/page1 to domain2/page1
domain1/page2 to domain2/page3
domain1/page3 to domain2/page5
...
Here's my webconfig <system.webserver> section:
<system.webServer>
<rewrite>
<rules>
<rule name="redirect single page" patternSyntax="ExactMatch" stopprocessing="true">
<match url="domain1/page1"/>
<action type="redirect" url="domain2/page1" appendquerystring="false"/>
</rule>
</rules>
</rewrite>
<httpredirect enabled ="true" destination"Domain2" httpresponsestatus="permanent"/>
</system.webServer>
But the redirecting is not happening it still points to the old domain pages.
Accordingly the #Claus answer on the question: 301 Redirect one domain to another using web.config
You can use the following code to achieve this:
<system.webServer>
<rewrite>
<rules>
<rule name="redirect" enabled="true">
<match url="(.*)" />
<conditions>
<add input="{HTTP_HOST}" negate="true" pattern="^www.domain1.com$" />
</conditions>
<action type="Redirect" url="http://www.domain2.com/{R:0}" appendQueryString="true" redirectType="Permanent" />
</rule>
</rules>
</rewrite>
<system.webServer>
This example will match all URLs unless the hostname part is exactly www.domain1.com - and redirect those to www.domain2.com/whatever.

Proper method to remove www from address using IIS URL Rewrite

What is the optimal way to remove the www subdomain from a url using IIS URL Rewrite?
If you want it to work with any hostname (not hardcoding it into the rule), you'd want to do something like this:
<rule name="Remove www" stopProcessing="true">
<match url="(.*)" ignoreCase="true" />
<conditions logicalGrouping="MatchAll">
<add input="{HTTP_HOST}" pattern="^www\.(.+)$" />
</conditions>
<action type="Redirect" url="http://{C:1}/{R:0}" appendQueryString="true" redirectType="Permanent" />
</rule>
in the redirect action, the {C:1} contains the second capturing group in the condition, whereas the {R:0} contains whatever was in the rule (the path). appendQueryString="true" will also append any querystring to the redirect (if present). Keep in mind though, that any url hashes, if present, will be lost in the process since those don't get passed to the server.
IIS does it automatically for you:
Select site > URL rewrite > new rule > Canonical Host Name :)
The following one should work :
<system.webServer>
<rewrite>
<rules>
<rule name="Remove WWW" stopProcessing="true">
<match url="^(.*)$" />
<conditions>
<add input="{HTTP_HOST}" pattern="^(www\.)(.*)$" />
</conditions>
<action type="Redirect" url="http://www.example.com{PATH_INFO}" redirectType="Permanent" />
</rule>
</rules>
</rewrite>
</system.webServer>
To do a redirect that will work for both http and https the following can be used
<rewrite>
<rules>
<rule name="Lose the www" enabled="true" stopProcessing="true">
<match url="(.*)" ignoreCase="true"/>
<conditions logicalGrouping="MatchAll">
<add input="{HTTP_HOST}" pattern="^www\.(.*)$"/>
</conditions>
<action type="Redirect" redirectType="Permanent" url="{SchemeMap:{HTTPS}}://{C:1}/{R:1}" appendQueryString="true" />
</rule>
</rules>
<rewriteMaps>
<rewriteMap name="SchemeMap">
<add key="on" value="https" />
<add key="off" value="http" />
</rewriteMap>
</rewriteMaps>
</rewrite>

Windows Server Web.config Strip Index Filename

I am using the following web.config file to redirect the non-www version of a site to the www version. However, I would also like to have it strip the file name of the index file as well.
For example:
redirecting www.example.com/index.html to www.example.com
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true" />
<rewrite>
<rules>
<rule name="CanonicalHostNameRule" stopProcessing="true">
<match url="(.*)" />
<conditions>
<add input="{HTTP_HOST}" pattern="^www\.example\.com$" negate="true" />
</conditions>
<action type="Redirect" url="http://www.example.com/{R:1}" />
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>
Edit:
Here is my updated config file. But, its causing a 500 error, now.
See CodingGorilla's answer below :)
In order to get rid of the index.html after the redirect, drop the {R:1}. But then you will need to modify that rule so that it triggers only for /index.html requests and create a new rule that triggers on other pages that includes the {R:1} so that requests for example.com/mypage.html will still get redirected properly.
Edit:
Edit #2
And the final answer is!
Based on our chat conversation, I think this is the final rule set:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true" />
<rewrite>
<rules>
<rule name="CanonicalHostNameRule1" stopProcessing="true">
<match url="index\.htm(?:l)?" />
<conditions>
<add input="{HTTP_HOST}" pattern="example\.com$" />
</conditions>
<action type="Redirect" url="http://www.example.com/" />
</rule>
<rule name="CanonicalHostNameRule2" stopProcessing="true">
<match url="(.*)" />
<conditions>
<add input="{HTTP_HOST}" pattern="^example\.com$" />
</conditions>
<action type="Redirect" url="http://www.example.com/{R:1}" />
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>

Resources