Apache rewrite rule for root domain

Needed to have Apache rewrite http://example.com to http://www.example.com to avoid having some apps blow up on us. Here’s the winning recipe.


First of all, this is the kind of thing I usually try to implement using an .htaccess file whenever possible, to avoid having to reload the server config multiple times during testing and after deployment.

Rewrite Engine On
Rewrite Base /
RewriteCond %{HTTP_HOST} !^www.example.com$ [NC]
RewriteRule ^(.*)$ http://www.example.com$1 [R=301,L]

This should work for Apache 1.3 or 2.x, as the regex engine hasn’t really changed much between versions (other than hopefully becoming more reliable/predictable). Notice that there’s no forward slash (“/”) betweeen “.com” and “$1”, that’s intentional. If you put one there you’d see a double-slash in the browser url (although it would still work!).

Basically this rule:

1. Fixes the base directory for rewrites to DocumentRoot (“/”);

2. Sets as a condition that the incoming url to be rewritten not (case-insensitively) match ultimate the target (here, http://www.example.com);

3. Rewrites anything coming in to another URL (here, http://www.example.com), returning a “301” (moved permanently) to the browser.

This is another variation, targeting requests that come in for http://example.com and only that url:

RewriteEngine On
RewriteCond %{HTTP_HOST} ^example.com$ [NC]
RewriteRule ^(.*)$ http://www.example.com$1 [R=301,L]

Even though I’m going to refer everyone to the Apache Rewrite Guide, the fact is that in this instance it took a bit of tweaking to come up with the above. Using the example given in the guide didn’t work for us. Maybe it’s just that some of us (like me) are too literal, but in the end learning by doing was the name of the game.

Here’s a really “greedy” alternative where you want to unconditionally redirect a whole site to someplace else:

RewriteEngine On
RewriteRule /.* http://www.example.com/ [R=301,L]

While the previous example was set in an .htaccess file, this one was set up in a block. Because the whole site covered by this virtual host was being redirected, there was no reason to set the RewriteBase or RewriteCond. Again, the response is forced to “301” (the default would be to make it a “302” or “found”) and the “L” is dropped in there to tell the rewrite engine that’s the last instruction for it to process.

If you really want to telegraph that a redirect is temporary, you should use a code “307” thus (this is especially helpful where both the client and the app are using a lot of caching to trick users into thinking their performance is better than it really is):

RewriteEngine On
RewriteRule .* http://www.example.com [R=302,L]

Note well that while it doesn’t matter where you put something like this in an IP based virtual host, positioning is everything when you’re dealing with Name Virtual Hosts in Apache. When a server configured for Name Virtual Hosts can’t match incoming traffic to a url, it will always default to the first Name Virtual Host. Always keep that in mind when you’re rewriting urls with greedy matching like in the above examples.

Here’ an Apache Rewrite Cheatsheet, which is nice because it lists on one page all the various directives and flags you can use in rewriting — so you don’t have to dig through reams of Apache doc for them.