IIS URL Rewrite negate conditions not working - iis

I want to redirect some pages from an old website (oldsite.com) to a new website (newsite.*) according to the following rules:
All first-level children (/sv, /no, /da, etc) should redirect to their respective counterparts, i.e. newsite.se, newsite.no, newsite.dk, etc.
All other children/descendants should redirect to the root of the new sites as well, except /page1 and /page2 and its descendants.
For this I've created the following rules (for sv in this case):
<rule name="Redirect /sv to .se" stopProcessing="true">
<match url="^sv/?$" />
<action type="Redirect" url="http://newsite.se" />
</rule>
<rule name="Redirect /sv/* except some pages" stopProcessing="true">
<match url="^sv/.+" />
<conditions logicalGrouping="MatchAll">
<add input="{REQUEST_URI}" pattern="^sv/page1(.*)" negate="true" />
<add input="{REQUEST_URI}" pattern="^sv/page2(.*)" negate="true" />
</conditions>
<action type="Redirect" url="http://newsite.se" />
</rule>
The first rule works fine but not the second. The problem is that my negated conditions don't seem to work. When I enter oldsite.com/sv/page1 I still get redirected to newsite.se. Maybe I've misunderstood how negated conditions work, but shouldn't the second rule execute the action if and only if both conditions are true (evaluate to false), i.e. the REQUEST_URI doesn't match /page1 and /page2?

You understand the concept very well.
The only problem is that the {REQUEST_URI} always start with a /, and the url never matches with a pattern like ^sv/page1(.*), finally you have a brand new false positive.
So, you need to include leading slashes in the pattern.
<add input="{REQUEST_URI}" pattern="^/sv/page1(.*)" negate="true" />
<add input="{REQUEST_URI}" pattern="^/sv/page2(.*)" negate="true" />

Related

Rewrite/Redirect rule in IIS causing trailing slash

I am using 3 domain-agnostic rewrite rules in my IIS. First i redirect from HTTP to HTTPS, then i redirect from naked-domain to www and in the end i remove .php from the URL by rewrite.
However, i see that whenever i access a page which is a subfolder and i access the index page in it, a trailing slash is added in the end of the url. Example:
Root -> subfolder called Items with an index.php in it
URL - www.xxx.net/items/
If i access a file other than index.php inside that folder it doesn't have a trailing slash
Root -> subfolder called Items with 2.php in it
URL - www.xxx.net/items/2
Normally, i wouldn't care but i noticed that google and the crawlers consider www.xxx.net/items and www.xxx.net/items/ as different entities which causes issues.
I know it's something easy but can't pinpoint it right now. Can someone show me how to get rid of this behaviour?
Here are the rules:
<rewrite>
<rules>
<rule name="HTTP/S to HTTPS Redirect" enabled="true" stopProcessing="true">
<match url="(.*)" />
<conditions logicalGrouping="MatchAny">
<add input="{SERVER_PORT_SECURE}" pattern="^0$" />
</conditions>
<action type="Redirect" url="https://{HTTP_HOST}{REQUEST_URI}" redirectType="Permanent" />
</rule>
<rule name="Redirect naked domain to www" stopProcessing="true">
<match url="(.*)" />
<conditions logicalGrouping="MatchAll">
<add input="{HTTP_HOST}" negate="true" pattern="^www\." />
</conditions>
<action type="Redirect" url="https://www.{HTTP_HOST}{REQUEST_URI}" appendQueryString="false" redirectType="Permanent" />
</rule>
<rule name="Remove PHP" stopProcessing="true">
<match url="^(.*)$" />
<conditions logicalGrouping="MatchAll">
<add input="{REQUEST_FILENAME}" matchType="IsFile" ignoreCase="false" negate="true" />
<add input="{REQUEST_FILENAME}.php" matchType="IsFile" ignoreCase="false" />
</conditions>
<action type="Rewrite" url="{R:1}.php" />
</rule>
</rules>
</rewrite>
After reading a lot about it, it turns out that this is very expected behaviour and you need to factor it in. Basically when you know that you going to get a trailing slash, make sure that your links pointing to this page also include trailing slash in the end so you don't get a redirect.

Setting up URL Rewrite rule for a specific domain

For local dev testing, I need to catch all requests to www.somedomain.com/XXX (where X is the path), and send them on to localhost/somevdir/XXX.
I've added this to my HOSTS file (c:\windows\system32\drivers\etc):
127.0.0.1 www.mydomain.com
Then, in IIS8 (Windows 8), I've added a binding to my "Default Web Site" for the host www.mydomain.com. This works, I can now browse www.mydomain.com/test.html and see a test html page. My virtual dir is inside the Default web site. I then add a URL Rewrite URL to the web site for the last bit:
<rewrite>
<rules>
<rule name="mydomain.com" stopProcessing="true">
<match url="^www.mydomain.com/(.*)" />
<action type="Rewrite" url="localhost/MyVDir/{R:1}" logRewrittenUrl="true" />
</rule>
</rules>
</rewrite>
But - that doesn't work. I get a 404 so it looks the the match never happens. I've tried redirect and rewrite, and I've tried without the ^ in the regex and a few other regex tweaks. Can someone explain what I've done wrong?
I think the following should work:
<rule name="mydomain.com" stopProcessing="true">
<match url="(.*)" />
<conditions logicalGrouping="MatchAll">
<add input="{HTTP_HOST}" pattern="^(mydomain\.com|www\.mydomain\.com)$" />
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
</conditions>
<action type="Redirect" url="http://localhost/MyVDir/{R:1}" redirectType="Temporary" />
</rule>
The match on any URL makes sure the conditions are checked, and the HTTP_HOST server variable seems the most reliable way of checking the requested hostname. You could remove the REQUEST_FILENAME input condition, but it works as quite a nice sanity check to make sure static files are always served.
The following is better for catching both www. and non-www. versions of the domain so that you don't have to write the domain twice, which could possibly cause errors with being twice as likely to write a typo. (The parenthesis with the ? character means optional in regex terms.)
<rule name="mydomain.com" stopProcessing="true">
<match url="(.*)" />
<conditions logicalGrouping="MatchAll">
<add input="{HTTP_HOST}" pattern="^(www.)?mydomain\.com$" />
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
</conditions>
<action type="Redirect" url="http://localhost/MyVDir/{R:1}" redirectType="Temporary" />
</rule>

Rewriting URLs in IIS7

I have been following http://learn.iis.net/page.aspx/806/seo-rule-templates/, which is a nearly perfect guide to creating SEO friendly URLs in IIS7.
I have one problem though:
If I create a rule to rewrite www.domain.com/contact/ I get in web.config:
<rule name="RewriteUserFriendlyURL1" stopProcessing="true">
<match url="^([^/]+)/?$" />
<conditions>
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
</conditions>
<action type="Rewrite" url="?p={R:1}" />
</rule>
But then i can't do www.domain.com/contact/send/.
If I create a rule to rewrite www.domain.com/contact/send/ I get in web.config:
<rule name="RewriteUserFriendlyURL1" stopProcessing="true">
<match url="^([^/]+)/([^/]+)/?$" />
<conditions>
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
</conditions>
<action type="Rewrite" url="?p={R:1}&a={R:2}" />
</rule>
But then I can't do www.domain.com/contact/
Both of the rules do so that I can't see any scripts, css og images from my /scripts/, /css/ and /images/ folders.
How do I make a rule to match both AND to NOT match the 3 folders mentioned above?
Your rule could be something like this (I have expanded and commented it for an easier understanding and eventual editing):
^
(
(?!css|scripts|images) # The directories you don't want to match
[^/]+ # The matched directory
)
(
/
(
([^/]+) # Optional part
/? # Optional trailing slash
)?
)?
$
Which translates into the following:
<match url="^((?!css|scripts|images)[^/]+)(/(([^/]+)/?)?)?$" />
The rewrite url should then be updated to: ?p={R:1}&a={R:4} because of the changes in the number of captures of the new regular expression.

URL Rewrite module for IIS7 Not Handling Rewrite Rule Correctly

I have the attached redirect and rewrite rules. Essentially, www.foo.com/vehicles/vehicle-detail.aspx?stockno=123456 is rewritten to www.foo.com/123456. This works as expected with the rules I have in place. Now, if I attempt to browse to a page that does not exist (i.e. www.foo.com/test.aspx) the rewrite rule qualifies and IIS attempts to forward the request to www.foo.com/vehicles/vehicle-detail.aspx (without the querystring). On the vehicle-detail.aspx page I have code to redirect to the homepage if there isnt a valid stockno in the querystring, so this is what is happening. I am not sure how to correct the rule(s), so that the condition does not qualify as true. I have attached rules and screenshots of Failed Request Tracing I enabled to watch the request/rewrite rule.
<rule name="Redirect StockNo" enabled="true" stopProcessing="true">
<match url="^Vehicles/Vehicle-Detail\.aspx$" />
<conditions logicalGrouping="MatchAll" trackAllCaptures="false">
<add input="{REQUEST_METHOD}" pattern="^POST$" negate="true" />
<add input="{QUERY_STRING}" pattern="^stockno=([^=&]+)$" />
</conditions>
<action type="Redirect" url="{C:1}" appendQueryString="false" />
<rule name="Rewrite StockNo" enabled="true" stopProcessing="true">
<match url="^([^/]+)/?$" />
<conditions logicalGrouping="MatchAll" trackAllCaptures="false">
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
</conditions>
<action type="Rewrite" url="Vehicles/Vehicle-Detail.aspx?stockno={R:1}" />
What you need is something more unique for the friendly pattern. If you know that it's always going to be digits, you can have:
<match url="^([\d]+)/?$" />
This will only match to www.foo.com/{digits} with an optional trailing slash.
Another option is to make the url something like www.foo.com/s/{stockno}/. With the /s/ you have something unique that you can confidently match. S is just an example that is short for stockno, so you can use what you want.

IIS 7 URL Rewrite - CamelCase domain and lower case everything else

I am trying to setup rewrite rules for my site in iis 7 with the URL Rewrite module. If the site name is "WonderfulWidgets"
I want it to always be http://WonderfulWidgets.com.
NOT: wonderfulwidgets.com
NOT: WONDERFULWIDGETS.com
I also want everything after WonderfulWidgets.com to be lower case.
IE WonderfulWidgets.com/best-widgets.
I have accomplished the lower case url rewrite and I have also made it so it will remove any leading www before WonderfulWidgets.com
My problem is my lower case URL rewrite lowers the domain name too. I need help writing the CamelCase domain name that works with rewriting everything else as lower case.
Here's what I have in my web.config:
<rewrite>
<rules>
<rule name="CanonicalHostNameRule1">
<match url="(.*)" />
<conditions>
<add input="{HTTP_HOST}" pattern="^WonderfulWidgets\.com$" negate="true" />
</conditions>
<action type="Redirect" url="http://WonderfulWidgets.com/{R:1}" />
</rule>
<rule name="RemoveTrailingSlashRule1" stopProcessing="true">
<match url="(.*)/$" />
<conditions>
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
</conditions>
<action type="Redirect" url="{R:1}" />
</rule>
<rule name="Default Document URL Rewrite" stopProcessing="true">
<match url="(.*?)/?Default\.aspx$" />
<action type="Redirect" url="{R:1}/" />
<conditions>
<add input="{URL}" pattern="WebResource.axd" negate="true" />
</conditions>
</rule>
</rules>
</rewrite>
DNS names are generally treated as case insensitive, and so most (all?) web browsers display the domain name in all lower-case in the address bar. To my knowledge you cannot change this behavior via changing what you return in your HTTP response.
From RFC 4343:
According to the original DNS design decision, comparisons on name
lookup for DNS queries should be case insensitive.
From Wikipedia:
Domain names are interpreted in case-independent manner.
The browsers all seem to prefer lower-case presentation.

Resources