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

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.

Related

Web.config Ignore all subdomains while redirecting non www to www

I am using a web.config to redirect all non www to www which is working fine. How do I add a rule to ignore all subdomains so http://example.com redirects to http://www.example.com but any subdomain http://*.example.com or http://one.example.com do not redirect to www. (I cannot add the list of subdomains).
<rule name="Redirect to www">
<match url=".*" />
<conditions logicalGrouping="MatchAny">
<add input="{HTTP_HOST}" pattern="^(www\.)(.*)$" negate="true" />
</conditions>
<action type="Redirect" url="http://www.{HTTP_HOST}" redirectType="Permanent"/>
</rule>
I think Joey's answer only covers the cases where domains are ending in .com and can't handle cases like .co.uk .co.za .com.au etc. You can extend the regular expression a little more but allowing for different types of domains using [a-z] will end up redirecting the subdomains as well, which is what you don't want according to the question.
So in order to achieve this, you'll have to handle the specific cases that you think can arise in your situation.
<rule name="Redirect to www">
<match url=".*" />
<conditions logicalGrouping="MatchAny">
<add input="{HTTP_HOST}" pattern="^([a-z-]+[.](com|co|ca|net)([.](uk|sg|au)){0,1})$" negate="false" />
</conditions>
<action type="Redirect" url="http://www.{HTTP_HOST}" redirectType="Permanent"/>
</rule>
You can modify the regular expression to your liking.
You could try to with the following code:
<rules>
<rule name="Redirect to www">
<match url="(.*)" />
<conditions>
<add input="{HTTP_HOST}" pattern="^example\.com$" negate="true" />
<add input="{HTTP_HOST}" pattern="^one\.example\.com$" negate="true" />
</conditions>
<action type="Redirect" url="http://www.{HTTP_HOST}/{R:0}"/>
</rule>
</rules>

How to apply URL Rewrite rules correctly for IIS applications

We have an IIS 8.5 setup where a single website is bound to domain.com and contains a number of IIS applications accessed as domain.com/app1, domain.com/app2 etc.
Each of these applications points to the same physical path, so they all share a web.config. This is a specific CMS configuration.
I have applied the usual URL Rewrite rules (redirect to HTTPS, enforce lowercase, add trailing slash etc.) to the web.config each application shares but have realised these rules are only applied to the URL after the application name. The rules I have are just standard rules added using the URL Rewrite GUI:
<rewrite>
<rules>
<rule name="Enforce lowercase" stopProcessing="true">
<match url="[A-Z]" ignoreCase="false" />
<action type="Redirect" url="{ToLower:{URL}}" redirectType="Permanent" />
</rule>
<rule name="Add trailing slash" 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}/" redirectType="Permanent" />
</rule>
<rule name="Redirect to HTTPS" stopProcessing="true">
<match url="(.*)" />
<conditions>
<add input="{HTTPS}" pattern="^OFF$" />
</conditions>
<action type="Redirect" url="https://{HTTP_HOST}{REQUEST_URI}" redirectType="Permanent" />
</rule>
</rules>
</rewrite>
So, for example, http://domain.com/APP1/PATH redirects to https://domain.com/APP1/path/. Also, https://domain.com/app1 doesn't redirect to https://domain.com/app1/.
The HTTPS rule is fine, but can anyone tell me how I can configure the other 2 rules so that they work with the entire URL, bearing in mind that the specific application name (app1, app2 etc) needs to be handled generically.
UPDATE
I've discovered that I can enforce lowercase URLs using a global rule in IIS (at server level) which is sufficient for my needs. But it doesn't seem to be possible to replicate the website-level rule for adding/removing trailing slash.
You just need to change action URL.
<rule name="Add trailing slash" 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="https://{HTTP_HOST}{REQUEST_URI}/" redirectType="Permanent" />
</rule>

IIS 7.5 URL Rewrite Module - Rewrite Maps with variables

I have several pages on my site that have long and unreadable URLs that I'd like to be able shorten. The problem I'm having is appending query strings with variable values.
For example:
"www.example.com/dir1/dir2/filename.php" shortens to "www.example.com/file".
"www.example.com/dir1/dir2/filename.php?id=2" would be "www.example.com/file/2".
"www.example.com/dir1/dir2/filename.php?id=2&alt=6" would be "www.example.com/file/2/6".
The values of 'id' and 'alt' are then used by our page to access information in our database, which determines the contents of the page. These values can change, and there is no set amount.
Right now I've got the first example working fine using the following rewrite rules:
<rewrite>
<outboundRules>
<remove name="OutboundRewriteUserFriendlyURL1" />
</outboundRules>
<rewriteMaps>
<rewriteMap name="StaticRewrites">
<add key="/file" value="/dir1/dir2/filename.php" />
</rewriteMap>
</rewriteMaps>
<rules>
<rule name="Rewrite Rule">
<match url=".*" />
<conditions>
<add input="{StaticRewrites:{REQUEST_URI}}" pattern="(.+)" />
</conditions>
<action type="Rewrite" url="{C:1}" />
</rule>
</rules>
</rewrite>
But I haven't been able to find anything that would allow the URLs to contain variables. Everything I've seen has used static rewrites like my current solution is using, and I can't find anything about allowing arbitrary parameters.
EDIT:
Found a better solution that doesn't use a Rewrite Map. I had attempted a simliar rule previously, but due to the IIS setup on our testing environment it wasn't working as expected. This version should work for most people.
<rule name="Curricula View" stopProcessing="true">
<match url="/file(?:/(\d+)(?:/(\d+))?)?" />
<action type="Rewrite" url="/dir1/dir2/filename.php?id={R:1}&alt={R:2}" appendQueryString="true" />
<conditions>
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
</conditions>
</rule>
Using this rule I was able to avoid using a rewrite map altogether. I had attempted to use something like this originally, but due to the setup of our test environment it wouldn't work without some weird tweaks. This version should work in all normal environments.
<rule name="Curricula View" stopProcessing="true">
<match url="/file(?:/(\d+)(?:/(\d+))?)?" />
<action type="Rewrite" url="/dir1/dir2/filename.php?id={R:1}&alt={R:2}" appendQueryString="true" />
<conditions>
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
</conditions>
</rule>
EDIT:
I was also able to get the original version with a rewrite map working for anyone interested.
<rule name="Rewrite Map with Variables" enabled="true">
<match url="^(.+?)/?/(.*)$" />
<conditions logicalGrouping="MatchAny" trackAllCaptures="false">
<add input="{ProductMap:{R:1}}" pattern="(.+)" />
</conditions>
<action type="Rewrite" url="/dir1/dir2/filename.php?id={C:0}&other={R:2}" appendQueryString="true" />
</rule>

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>

Use urlrewrite to rewrite all requests to root

I want to use web.config and IIS's urlrewrite to rewrite all requests to a certain directory to the root, for example:
From:
mydomain.com/directory/test.php
To:
mydomain.com/test.php
and
From:
mydomain.com/directory/test/test.php
To:
mydomain.com/test/test.php
All parameters, etc should be passed as well. Any idea how to do this using web.config?
I had a requirement for this a while back and found this:
Using Url rewrite to "delete" a folder
There's a small error in the rule which was corrected later by the poster. Here's a copy with the correction should the link dry up (I also made it a bit more generic for your requirements):
<rewrite>
<rules>
<rule name="RemoveDirectory" stopProcessing="true">
<match url="^directory$|^directory/(.*)$" />
<conditions>
</conditions>
<action type="Redirect" url="{R:1}" />
</rule>
<rule name="RewriteToFile">
<match url="^(?!directory/)(.*)" />
<conditions>
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
</conditions>
<action type="Rewrite" url="directory/{R:1}" />
</rule>
</rules>
</rewrite>
Just search and replace directory with your directory name.

Resources