Example Clean URL configuration of httpd.conf for performance

This was tested and applies to FC4/php5/Apache 2.0.54.

Enabling .htaccess in Apache requires more work on the part of the server. A full explanation can be found here:
http://www.serverwatch.com/tutorials/article.php/3436911
Suffice it to say that it is in your interest to not use .htaccess files and even disable them if you are concerned about squeezing more performance out of apache.

I moved the rewrite rules (all of the sample .htaccess file really) to /etc/httpd/conf/drupal.conf. Then for each virtual host, one can add the line:

Include conf/drupal.conf

The rewrite rules change slightly:
  # Rewrite current-style URLs of the form 'index.php?q=x'.
  RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} !-f
  RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} !-d
  RewriteRule ^(.*)$ /index.php?q=$1 [L,QSA]

Note that I added %{DOCUMENT_ROOT} and a leading slash in front of index.php -- because I have index.php installed in my document root. If you install it in another directory, you will want to give the relative path to it from document root with the leading slash.

Important: If you forget the leading slash (more specifically, forget to give the relative path with leading slash), Apache will give you a "400 Bad Request" error.

This is better. But we still have a problem where every request will check for the existence of a file and a directory before we apply the rewrite rule. The OS may be able to cache some of that information, but it would still be better to avoid the two file-system checks in the first place.

There are some directories that we should not rewrite. And there are certain extensions that we should not rewrite. Using this information, we can update the rewrite rule to send everything to index.php that does not fall into this category. The first rule excludes the directories "files", "misc", and "uploads". The second rule excludes the extensions you see. Add more if you have other extensions in your directory that should not get passed to index.php.

  RewriteCond  %{REQUEST_FILENAME} !^/$
  RewriteCond  %{REQUEST_FILENAME} !^/(files|misc|uploads)(/.*)?
  RewriteCond  %{REQUEST_FILENAME} !\.(php|ico|png|jpg|gif|css|js|html?)(\W.*)?
  RewriteRule ^(.*)$ /index.php?q=$1 [L,QSA]

Make sure to specify $base_url.

RobRoy - August 31, 2006 - 00:09

Make sure to specify $base_url when using the %{DOCUMENT_ROOT} method above. Once I did my funky theming errors went away.

See http://drupal.org/node/9418#comment-149892.
--
Rob
Founder and Director
Electronic Insight Corporation

Recent Drupal Projects: MP3PIG | MySpace Layouts

Is it the first, second or both?

ChuckL - October 11, 2006 - 21:21

I am a real newbie to mod_rewrite and I would like to try this but I cannot figure out whether you use the first set of rules, the second set of rules or both. If you use both how should they be placed?

Do I place them exactly as you have listed them, for example:

  # Rewrite current-style URLs of the form 'index.php?q=x'.
  RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} !-f
  RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} !-d
  RewriteRule ^(.*)$ /index.php?q=$1 [L,QSA]
  RewriteCond  %{REQUEST_FILENAME} !^/$
  RewriteCond  %{REQUEST_FILENAME} !^/(files|misc|uploads)(/.*)?
  RewriteCond  %{REQUEST_FILENAME} !\.(php|ico|png|jpg|gif|css|js|html?)(\W.*)?
  RewriteRule ^(.*)$ /index.php?q=$1 [L,QSA]

Any help would be really appreciated.

Regards,

ChuckL

Bump

johsw - February 18, 2007 - 11:18

I would really like to know that as well !!! :-)

the second set replaces the

irstudio - June 1, 2007 - 22:17

the second set replaces the first,
but is not as robust (i.e. funny things might happen :))), so use with care

Just include (a copy of) .htaccess in the Directory block

dman - July 31, 2007 - 12:46

I found it even easier than that.
My approach was to leave the .htaccess original nearby, but include it at startup, and ignore it from then on. Basically the same approach, but I didn't discover the need to edit it at all. I placed the include in the directory context and it behaved as it it was found there. Perhaps I'm lucky.

First, get clean URLs working out-of the box, then:
(siteroot is of course /var/www/drupal and the site instance is called drupalsite also. This example is Debian-Ubuntu/Apache2)

mv /var/www/drupalsite/.htaccess /var/www/drupalsite/htaccess.conf

This disables it again temporarily, but leaves the file as part of the site. If you want to copy instead, you must MOVE the .htaccess file away otherwise it will contine to be read.
#> vi /etc/apache2/sites-enabled

<VirtualHost *>
        ServerName drupalsite.example.com
        DocumentRoot /var/www/drupalsite
        <Directory /var/www/sdrupalsite>
                Order allow,deny
                Allow from all
                Options +FollowSymLinks +ExecCGI
                RewriteEngine On
                AllowOverride All

                # Instead of reading .htaccess rules on the fly every page,
                # Include them once, now, in this directory context
                Include /var/www/drupalsite/htaccess.conf
        </Directory>
</VirtualHost *>

#> apache2ctl -t
#> apache2ctl restart

The rewrite rules or .htaccess file from the Drupal distro did not have to be modified at all, and I did not have to hardcode a $base_url in my settings.conf.

So far so good. I've not tested with subdirectories yet.

The tips on skipping filename extensions are probably good, but may conflict with 'private' file storage issues.

.dan.
How to troubleshoot Drupal | http://www.coders.co.nz/

Why not just point to the file directly?

mattman - October 29, 2007 - 07:56

<VirtualHost 192.168.1.2:80>
DocumentRoot /home/drupal
ServerName example.com
ErrorLog /var/log/httpd/sites/example.com_error-log
CustomLog /var/log/httpd/sites/example.com_access-log "combined"

<IfModule mod_rewrite.c>
RewriteLog logs/sites/example.com_rewrite-log
#RewriteLogLevel debug
</IfModule>

<Directory "/home/drupal/>
AllowOverride none
# Read in Drupal default .htaccess file asif conf
Include /home/drupal/.htaccess
</Directory>

</VirtualHost>

The above seems to work fine for me. Plus, if you maintain a cvs version of drupal right next to live copy then all you have to do is run a diff to get updates for security changes.

diff -ur older_folder/ newer_folder/ > drupal-update.diff

Then apply the patch after review and you have a very quick system of updating.

Well...

dman - October 29, 2007 - 13:53

Yes, I could have turned off AllowOverride altogether, as you did, but I chose not to. I have an eclectic bunch of sites, and I sorta liked having it around. Disabling it altogether didn't make me happy, as it would leave me headscratching at some later date about why the **** something obvious wasn't working...

For the performance boost, tweaking apache2.conf even more will probably be even more successful I guess.

.dan.
How to troubleshoot Drupal | http://www.coders.co.nz/

 
 

Drupal is a registered trademark of Dries Buytaert.