In a shared hosting
environment, it’s a common desire to have a single IIS website that handles
multiple sites with different domain names. This saves the cost of
setting up additional sites with the hoster.
At ORCS Web, we’ve supported this situation for many years using ISAPI
Rewrite. Now, withURL
Rewrite for IIS 7, it’s
easier and it’s integrated right into web.config. In this blog post I’ll
set out to cover the essentials for hosting multiple domain names under a
single account using URL Rewrite.
This post assumes that
you are using URL Rewrite 1.0, 1.1 or 2.0. I’ll follow-up in a later post
on more advanced ways to take this further yet, using the new features of URL
Rewrite 2.0.
Part II will cover the outgoing rules available in
URL Rewrite 2.0 to take this a step further.
First, the file
structure
Let’s lay out the
directory structure for this example. Assume that you have 3 domain
names. They are: masterdomain.com, site2.com and
hawaiivisit.site2.com. You’ve created your directory structure like this:
Let’s assume that
masterdomain.com was already in the root of the site and can’t easily be
moved. However, site2.com and hawaiivisit.site.com need to be set
up. Each of these folders have a website within them.
Directing the domain
name to the server
First, make sure that
when you browse to the website by domain name, that it resolves to the correct
IP address. This is handled at the DNS level. Your DNS entry for
site2.com and hawaiivisit.site2.com will often be identical to masterdomain.com
and are managed through your DNS provider.
Catching the site when
on the server
If you host with a web
hosting company then they will take care of this. If you host yourself,
make sure to set a site binding so that the expected site processes the domain
name. If you use host headers, be sure to add the extra bindings for
them.
Redirecting the site to
a subfolder
Now that you have the
domain name directed to the server and site, URL Rewrite comes in to direct it
to a subfolder.
First, make sure that
your web host supports URL Rewrite on the server that you’re hosted on.
The following assumes that it’s installed and supported.
You can use IIS 7
Manager which gives a friendly interface for creating rules. If you
prefer to write them directly in web.config, I’ll include the rules below.
First, open up URL
Rewrite:
I’ve come to prefer
RegEx rules instead of wildcard rules. I find that wildcard rules reach
their limit pretty quickly. Regular expressions can be daunting at first
but it’s pretty easy to pick up the basics. Here’s an excellent reference
to get started: http://www.regular-expressions.info/reference.html
To create the rule click
on “Add Rules…”.
Select the “Blank Rule”
template and click OK.
For the name, enter your
domain name, or whatever makes the most sense to you.
Match URL section
In the Match URL
Section, leave the defaults to match the pattern and Regular Expressions.
For the pattern, enter (.*) without the parentheses. The “URL” is the
part after the domain name. i.e. www.ThisIsTheDomain.com/ThisIsTheURL.
It’s the domain that we’re interested in now, not the URL.
Conditions
The Conditions section
is where we’ll do most of the work. Expand that section if it’s collapsed
and click “Add”.
The domain name is
contained within the HTTP header called {HTTP_HOST}. Here’s where the fun
comes. The regular expression pattern that will match www.site2.com or
site2.com (without the www) looks like this: ^(www.)?site2.com$.
Here’s what that
means.
- The ^ is the character that
signifies the start of the string. That ensures that
something.www.site2.com doesn’t also get included with this rule.
- The $ is the character that
marks the end of the string.
- ( ) parentheses are used to
create section groups.
- ? means that something is
optional.
- Therefore, (www.)? means that
with www. or without, either are accepted.
After filling in these
fields you should have something like the following:
Now, here’s the part
that many people wouldn’t guess at first. Since URL Rewrite works on the
URL only, while most code (ASP.NET, ASP, PHP, etc) works at the server level,
they aren’t aware of each other. Just because you rewrite the URL doesn’t
mean that the code has any clue of the change. As a result, any time that
ASP.NET automatically creates the path, it will likely clash with the URL
Rewrite rule. For example, Response.Redirect(“~/”) will redirect to the
root of the application. That means that it can create a path like
www.site2.com/site2. Notice the extra site2 in the path. The login
page for ASP.NET will mess with you too.
A future blog post will cover how to hide the /site2 using
URL Rewrite 2.0, but the easy solution is to ensure that www.site2.com and
www.site2.com/site2 both go to the same place. Both should be served from
…\masterdomain.com\site2. It means that the URL can be longer than you
may prefer, but it allows the site to continue to function.
To achieve this, add an
exclusion condition so that this rule doesn’t redirect at all if the URL starts
with /site2/.
There are 2 ways to
achieve this. You could go back to the URL section where we previously
entered .* and update that section. There isn’t anything wrong with that
at all. For no particular reason that I can think of right now, I prefer
to do this from the conditions section. Here’s how to do it:
Add another condition
where the condition input is {PATH_INFO}, and set the dropdown to “Does Not
Match the Pattern”, and set the Pattern to ^/site2/. That means that the
PATH_INFO must start with /site2/. Note that you shouldn’t end with the $
this time because you want sub-sub folders to work too. It should look
like this:
Action Section
We’re nearly done.
In the Action section, first set the “Action Type” to Rewrite. Then
set the Rewrite URL to \site2\{R:0} and ensure that the “Append query string”
checkbox is checked. The {R:0} is a back reference to the URL. It
will allow the URL to be carried through dynamically in the request. The
Append query string ensures that the query string itself will carry through.
The complete rule should
look like this:
That’s it. Save
and test.
Using a Text Editor
You may prefer to use a
text editor or to see the config directly. The rule generated for
web.config looks like this:
<rewrite>
<rules>
<rule name="site2.com" stopProcessing="true">
<match url=".*" />
<conditions>
<add input="{HTTP_HOST}" pattern="^(www.)?site2.com"
/>
<add input="{PATH_INFO}"
pattern="^/site2/" negate="true" />
</conditions>
<action type="Rewrite" url="\site2\{R:0}"
/>
</rule>
</rules>
</rewrite>
And, the rule for
hawaiivisit.site2.com is similar. It looks like this:
<rewrite>
<rules>
<rule name="hawaiivisit.site2.com" stopProcessing="true">
<match url=".*" />
<conditions>
<add input="{HTTP_HOST}"
pattern="^hawaiivisit.site2.com$" />
<add input="{PATH_INFO}"
pattern="^/hawaiivisit/" negate="true" />
</conditions>
<action type="Rewrite" url="\hawaiivisit\{R:0}"
/>
</rule>
</rules>
</rewrite>
The other things
I wanted to briefly
mention what isn’t covered in this blog post that you may want to
consider.
- DNS. The ‘how to’ for your
domain name purchase and directing isn’t covered here.
- Statistics. If you use a
client-side option like Google Analytics then this will work just as well
under a single account. However, if you are using a log based
statistics program like SmarterStats then it’s up to you to set rules in
SmarterStats to filter out or sub-divide the statistics into useful
sections i.e. 1 per site.
- Email. You will likely need to
setup another mail account with your host, or add the new domain as a
domain alias to your existing account.
- ASP.NET inheritance. web.config
inherits down the entire path but the ASP.NET folders do not inherit past
application boundaries. More on that here.
One workaround if ASP.NET inheritance fights with you is to not have a
site in the website root. Instead, place all sites in their own
subfolder.
- You’ll likely need to mark the
folder as an application so that it is an ASP.NET application.
(assuming ASP.NET of course)
No comments:
Post a Comment