htaccess tips and tricks
directory balancing
Sometimes you might end up in a situation where you want to spread your files across multiple directories without updating your links. The first thing to do is set RewriteEngine On
at the top of your .htaccess
file.
There are several ways to perform this. You might decide to move the files physically into a directory tree structure where the first letter of the file determines the directory where the file is stored.
When doing this, for html files for example you might do the following:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} ^/html/[^/]+$
RewriteRule ^(.)(.*)$ /html/$1/$1$2 [L]
Now requests will be filtered off to their directories based on their initial character if it doesn't exist in the parent already.
What we can do to further extend the directory balancing is split some of the content into two directories deep (in some cases but not all).
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} ^/html/([^/])([^/])([^/]+)$
RewriteCond /var/www/sites/example.test/html/%1/%2/%1%2%3 -f
RewriteRule ^(.)(.)(.*)$ /html/$1/$2/$1$2$3 [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} ^/html/([^/])([^/]+)$
RewriteCond /var/www/sites/example.test/html/%1/%1%2 -f
RewriteRule ^(.)(.*)$ /html/$1/$1$2 [L]
What we're doing in the above example is to test for the files' presence in the expected directories before altering the URI to reflect that. This could be further enhanced to use a Rewritemap, but this has its own draw backs such as having to be updated regularly when the directory contents update.
fix broken sites
Occasional site changes will require fix-ups later to redirect traffic. One of the many benefits of having mod_rewrite at your disposal is the ability to arbitarily redirect large chunks of your site to somewhere sensible. Consider, moving from a blog to a wiki, they both offer very similar features on different URL labels, so if your tags become categories you may wish to do something along these lines:
RewriteCond %{REQUEST_URI} ^/tag/([^/]+)/?$
RewriteRule ^ /wiki/Category:%1 [R=301,L]
This takes the second part of the URL (from /tag/<...>
) and appends that to the category part of the /wiki/
URL. This also tells the request that the item has moved permanently and no further URL rewriting should be done.
pesky referrers
Sometimes you get a situation where a client is problematic and you can only identify it by referrer.
In this case, we'd like to prevent client access if the referrer is set to "None".
RewriteCond %{HTTP_REFERER} ^None$
RewriteRule ^ - [F,L]
The F
sends a 'forbidden' response to the client. The L
makes this the last rewrite rule that is processed fro this request.
redirect non-www to www
RewriteEngine On
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule ^(.*)$ http://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
redirect www to non-www
RewriteEngine On
RewriteCond %{HTTP_HOST} ^www\.(.*) [NC]
RewriteRule ^(.*)$ http://%1%{REQUEST_URI} [R=301,L]