Mimsy Were the Borogoves

Hacks: Articles about programming in Python, Perl, PHP, and whatever else I happen to feel like hacking at.

mod_rewrite cheat sheet

Jerry Stratton, December 24, 2006

I’m in the middle of a site redesign for Negative Space, and one of the things I want to do is get rid of file extensions. This way, if I change a page from being straight HTML to being dynamically-generated from PHP, I don’t need to deal with redirects or telling the server to interpret all pages as PHP, or any of the other tricks that people use when they change the extension on a web page.

I want links to always be http://www.hoboes.com/Politics/Prohibition/ and never http://www.hoboes.com/Politics/Prohibition.html (or .php or any other .extension).

The files, however, still have to have those extensions, because that’s how the server recognizes what to do with them.

The obvious answer to this is Apache’s mod_rewrite. But the on-line instructions never seem to address the issues I’m running into; the on-line instructions appear to be organized in a manner designed to keep them from being used.

Dave Child has summarized and re-organized the mod_rewrite options in a single-page cheat sheet that I found invaluable when writing the rules for Negative Space.

  • RewriteEngine On
  • #If the request is for an existing directory, we're done
  • RewriteCond %{REQUEST_FILENAME} -d
  • RewriteRule ^(.*)$ - [L]
  • #Apache lets dynamic files accept slashes at the end
  • #redirect dynamic file endings to their "directory" equivalent
  • RewriteCond %{ENV:REDIRECT_STATUS} ^$
  • RewriteRule ^(.*)\.php/?$ /Search/$1/ [R,L]
  • #if it has no slash after it, and we haven't already redirected
  • #add a slash and start over
  • #if they actually ask for a .html/.php file, this will cause a 404 error
  • #but that's what we want
  • RewriteCond %{ENV:REDIRECT_STATUS} ^$
  • RewriteRule ^(.*[^/])$ /Politics/$1/ [R,L]
  • #Get the base path without the slash
  • RewriteRule ^(.*)/$ $1 [E=NEWCHECK:$1]
  • #If there is a .html file, use it
  • RewriteCond /usr/www/users/nspace/Politics/%{ENV:NEWCHECK}.html -f
  • RewriteRule ^(.*)/$ $1.html [L]
  • #If there is a .php file, use it
  • RewriteCond /usr/www/users/nspace/Politics/%{ENV:NEWCHECK}.php -f
  • RewriteRule ^(.*)/$ $1.php [L]

Everywhere where it does a “real” redirect ([R]), it first checks to make sure that we aren’t in a redirect loop by verifying that REDIRECT_STATUS is empty.

When redirecting from the old section to the new section (the URL is exactly the same except for not being in an "html" subdirectory), I remove the .html, .shtml, and .php endings from paths before redirecting them, so that they hopefully won’t be linked with the file endings:

  • RewriteEngine On
  • #redirect known file endings to their "directory" equivalent
  • RewriteRule ^(.*)\.(shtml|html|php)$ /Politics/$1/ [R,L]
  1. <- Compiling MOO
  2. ht://Dig and Quotes ->