Main Content

Simple but effective use of mod_rewrite (Apache httpd)

Archive - Originally posted on "The Horse's Mouth" - 2007-05-27 17:48:15 - Graham Ellis

[Index under mod_rewrite tutorial]

Do you want a single 'intelligent' web page to provide the content for tens or hundreds of URLs so that you don't have to write each similar page individually? Do you want to set up your server so that it will take any requests for ".htm" files and turn them into ".html"s? Do you want to rename a page, but still leave the old name in place too for anyone who has bookmarked it or linked to it?

If you're using the Apache httpd web server (and 70% of domains do use it!), then mod_rewrite is the tool you need to implement these functions. But alas, mod_rewrite is so flexible it's hard to know where to start, even with the reference manual to hand!

How do I rename a page but leave the old name in place?

RewriteEngine On
RewriteRule ^oldplace/oldname\.html$ newplace/newname.html


This is an example from the top level directory (document root) .htaccess file, redirecting references to oldname.html in the oldplace directory to newname.html in the newplace directory.

* You can add as many rewrite rules like this as you like - no need to turn the engine on every time

* The path names you give should be relative to the directory in which the .htaccess file is located.

* The old name is a REGULAR EXPRESSION - the ^ and $ mean "starting with" and "ends with" and I've added them in this example to avoid any risk of matching a url that INCLUDES the text pattern. The \ in front of the . means "I really want a dot" as by default a dot matches any character at all.

How do I accept .htm extensions as well as .html?

RewriteEngine On
RewriteRule ^(.*)\.htm$ .html


Literally "Anything that ends in .html is to be replaced by the same thing ending in .html"

How do I point all the .html URLs in a directory at a single intelligent page?

RewriteEngine On
RewriteRule ^(.*)\.html$ action.php?pagename=&%{QUERY_STRING}


This forwards ANY URL with a .html extension in the current of lower directories to a page called action.php, with a parameter called "pagename" that will contain the name of the page called.

Many, many pages on our web site use code similar to this - our wiki is comprised of pages that are generated from a MySQL database by a single script every time, and even the image library isn't individual files - in that case, we have a rewrite rule that points .jpg requests at a script. What might appear to be 28 different style sheets are really just one ...

Where do I configure mod_rewrite?

1. You place any OVERALL settings in the Apache httpd configuration file httpd.conf (in the case of SuSE Linux, or other tailored configurations, you might place the settings in a file that's included from httpd.conf

2. Any changes / additions your want to set DIRECTORY BY DIRECTORY should be placed in a file called .htaccess in each individual directory. The settings you make will then apply to that directory and anything below it unless overridden in another .htaccess file.

Extra Notes?

If you have several rewrite rules that match, you may find that your URL is rewriten multiple times. If you add [L] onto the end of a rewrite rule, it means "Last" so that mod_rewrite will stop at that point and not try to make further changes to the current URL.

If you add [P] (or [L,P]) onto the end of a rewrite rule, you'll make the new URL a proxy request; this means that you can redirect to a URL on another server, which your server will call up by pretending to be a client (browser).

You can also specify rewrite conditions and much more - once you're familiair with the techniques listed above you should probably go on and learn the ins and outs of them from the manual which you'll find much more readable.

Notes for PHP Programmers

If you are writing a script that need to know its own name, and you call it via mod_rewrite, which variable name contains the original URL called for, and which the rewritten one?

$PHP_SELF is the rewritten name
$_SERVER[REDIRECT_URL] is the original name
$_SERVER[REQUEST_URI] is the original name WITH get parameters