Apache's
mod_rewrite module is most commonly used to generate clean URLs, by covertly "rewriting" incoming paths to different internal paths. (Drupal rewrites
/some/url as
index.php?q=some/url and works off the querystring, for example.) It can also be used to overtly redirect users with the same kind of rules.
But mod_rewrite's flexibility allows it to be used for a whole lot more than simple URL handling. Regex patterns can be tested to set environment variables, for example (the kind retrieved with PHP's
getenv(). I recently started using rewrite rules in my Drupal root .htaccess files as an alternative to my
Environments module, for organizing all my server- and subdomain-differentiated logic in a central location.
This functionality is documented reasonably well at
Apache.org; see the
"Documentation" section at the bottom.
Here are some examples I'm using. They're all wrapped in:
<IfModule mod_rewrite.c>
RewriteEngine On
...
</IfModule>
This sets environment variables for each server environment:
## set env vars for domains
## dash indicates no subst
## '.*' (any string) is critical!! thanks http://www.askapache.com/htaccess/crazy-advanced-mod_rewrite-tutorial.html
# siteenv = local, live, dev
RewriteCond %{SERVER_NAME} ben.local
RewriteRule .* - [E=siteenv:local]
RewriteCond %{SERVER_NAME} ^benbuck.net$ [OR]
RewriteCond %{SERVER_NAME} ^benbuckman.net$
RewriteRule .* - [E=siteenv:live]
RewriteCond %{SERVER_NAME} ^dev.benbuck.net$
RewriteRule .* - [E=siteenv:dev]
Uncomment this for debugging:
## stop all following rules on local (for debugging)
## RewriteCond %{ENV:siteenv} local
## RewriteRule .* - [L]
This rule redirects tech.benbuck.net to benbuckman.net/tech. It excludes my local and dev sites, redirects (
[R]), and stops checking for other rules (
[L]):
# tech home
RewriteCond %{SERVER_NAME} ^tech.benbuck
RewriteCond %{ENV:siteenv} !local
RewriteCond %{ENV:siteenv} !dev
RewriteRule ^$ http://benbuckman.net/tech [R,L]
This powers the "shortcut" URLs which I use to tweet my posts.
!-f and
!-d exclude valid file and directory paths, respectively.
RewriteCond %{SERVER_NAME} ^benbuck.net$ [OR]
RewriteCond %{SERVER_NAME} ^benbuckman.net$
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^b/([0-9]*)/?$ http://benbuckman.net/node/$1 [L]
On a multi-site setup, RewriteRules can send
/files to
/sites/somesite/files based on the subdomain. (This only works for HTTP-requested paths, however; unlike symlinks, these rules have no effect on
include()'d paths, for instance.)
The next thing I'd like to try is virtual document roots (*.domain) that map to different folders.
If you have any other cool
mod_rewrite tips, or see any errors in my examples here, please post a comment!