Forum Moderators: phranque

Message Too Old, No Replies

301 non-www => www redirect on the server level

Full access to server, don't want to use .htaccess

         

ocon

5:37 pm on Oct 13, 2010 (gmt 0)

10+ Year Member Top Contributors Of The Month



I just got a server to play around with and I've learning how to setup a LAMP environment from scratch. Because I have full control over this computer, I can do things I didn't have access to before.

In the past I've used .htaccess to perform some functions that would have ideally been handled on the root level. Now, I'm able to set up some of these functions without .htaccess in a less server intensive manner.

The one thing I haven't figured out is how to do a 301 non-www => www redirect on the server level without having to use an .htaccess file.

Is this even possible? Or is handling it at the .htaccess level the proper and best way to perform this action?

Thanks for any help.

sublime1

12:35 am on Oct 14, 2010 (gmt 0)

10+ Year Member



ocon --

Anything possible in .htaccess is possible in a server or virtual host context (a few exceptions like RewriteBase). However there are a couple of important differences in the way certain things are handled, especially RewriteRule.

In .htaccess, assuming a RewriteBase of /, the path of a request will not start with a / -- in a Server or Virtual Host context it will. There are some other differences, in particular with how internal rewriting works (it's far simpler than in .htaccess).

For your case, which is known as domain canonicalization, the example from the Apache Rewriting Guide is designed to handle either context (although it is "wrong" for both!):


RewriteCond %{HTTP_HOST} !^www\.example\.com [NC]
RewriteCond %{HTTP_HOST} !^$
RewriteRule ^/?(.*) http://www.example.com/$1 [L,R,NE]


Note the RewriteRule pattern -- ^/?(.*) -- the first character, a / is not required for the pattern to match (that's what the ? does). So, in either context this will work, but I would argue that in a VirtualHost context, this is a better version:


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


The rewrite rule is different. I remove the (now) unnecessary test for the optional / -- it will be there, I change the "R" flag to "R=301" which causes the server to send a 301 "Moved Permanently" HTTP response, rather than the default "Moved Temporarily" 302 response. It is technically unnecessary for the regular expression to include the /, but I do this because I think it makes the substitution ("http://www.example.com/$1") a little more readable than ("http://www.example.com$1")

In the server/vhost context you have much, much more control. You can use the RewriteLog directive to help you understand and debug rewriting, and loads of other fun and useful thing also (assuming you are using a <VirtualHost> container, which I highly recommend, rather than putting directives directly in the server config, you'll know the possible hostnames because you specify the allowed values in ServerName and ServerAlias directives.

Have fun!

Tom

[edited by: sublime1 at 12:50 am (utc) on Oct 14, 2010]

sublime1

12:49 am on Oct 14, 2010 (gmt 0)

10+ Year Member



Oh, and an important point I forgot:

if you have access to your server configuration, it is almost always better, and always more efficient to use the server configuration rather than .htaccess.

.htaccess must be opened, parsed, interpreted and executed on every single request to the server, and in some cases, some parts of this will happen more than once.

Directives at the Server or VirtualHost context are read once: at server startup. They get warmed up once and remain at the ready for the life of the server. Also, because there's no uncertainty about whether there will be other directives to process, there is no multi-pass processing, and this not only takes less work, it also can simplify your rewrite rules.

There are valid arguments for continuing to use .htaccess -- mostly because this is what is assumed by many people writing documentation, answering questions, etc. But if you can rid your code of .htaccess, your life will be simpler.

Do remember that when adding processing to server or virtual host configuration files, you'll need to reload the server for the changes to take effect -- use
sudo apache2ctl -t
to test the validity of your changes, and
sudo apache2ctl graceful
to restart a server that has live traffic.

Tom

ocon

3:11 am on Oct 14, 2010 (gmt 0)

10+ Year Member Top Contributors Of The Month



Thank you very much, but when I try to restart Apache I get the following error:

Syntax error on line 30 of /etc/apache2/sites-enabled/...:
Invalid command 'RewriteCond', perhaps misspelled or defined by a module not included in the server configuration
...fail!

I'm making my changes inside the <VirtualHost> for this site.

sublime1

2:25 pm on Oct 14, 2010 (gmt 0)

10+ Year Member



Do you have a statement

RewriteEngine On

before any references to apache rewriting?

If so, use the command "sudo a2enmod rewrite" to enable mod_rewrite in your system. Note: I think this 'a2enmod' command is a Debian/Ububntu specific thing -- in other distros or older Apache installations you would need to go into /etc/apache2/apache2.conf or /etc/httpd/httpd.conf and uncomment the declaration for mod_rewrite module.

(And as a reminder, this is a reason to use the 'sudo apache2ctl -t' command to test your configuration before restarting apache :-) )

Tom