![]()
Apache HTTP Server Version 1.3
Module mod_rewrite
This module is contained in the
URL Rewriting Enginemod_rewrite.c
file, with Apache 1.2 and later. It provides a rule-based rewriting engine to rewrite requested URLs on the fly. It is not compiled into the server by default. To usemod_rewrite
you have to enable the following line in the server buildConfiguration
file:AddModule modules/standard/mod_rewrite.o
Summary
``The great thing about mod_rewrite is it gives you all the configurability and flexibility of Sendmail. The downside to mod_rewrite is that it gives you all the configurability and flexibility of Sendmail.''-- Brian Behlendorf
Apache GroupWelcome to mod_rewrite, the Swiss Army Knife of URL manipulation!`` Despite the tons of examples and docs, mod_rewrite is voodoo. Damned cool voodoo, but still voodoo. ''-- Brian Moore
bem@news.cmc.netThis module uses a rule-based rewriting engine (based on a regular-expression parser) to rewrite requested URLs on the fly. It supports an unlimited number of rules and an unlimited number of attached rule conditions for each rule to provide a really flexible and powerful URL manipulation mechanism. The URL manipulations can depend on various tests, for instance server variables, environment variables, HTTP headers, time stamps and even external database lookups in various formats can be used to achieve a really granular URL matching.
This module operates on the full URLs (including the path-info part) both in per-server context (
httpd.conf
) and per-directory context (.htaccess
) and even can generate query-string parts on result. The rewritten result can lead to internal sub-processing, external request redirection or even to an internal proxy throughput.But all this functionality and flexibility has its drawback: complexity. So don't expect to understand this module in it's whole in just one day.
This module was invented and originally written in April 1996
and gifted exclusively to the The Apache Group in July 1997 by
Ralf S. Engelschall
rse@engelschall.com
www.engelschall.com
Table Of Contents
Internal Processing
Configuration Directives
Miscellaneous
- RewriteEngine
- RewriteOptions
- RewriteLog
- RewriteLogLevel
- RewriteLock
- RewriteMap
- RewriteBase
- RewriteCond
- RewriteRule
Internal Processing
The internal processing of this module is very complex but needs to be explained once even to the average user to avoid common mistakes and to let you exploit its full functionality.
API Phases
First you have to understand that when Apache processes a HTTP request it does this in phases. A hook for each of these phases is provided by the Apache API. Mod_rewrite uses two of these hooks: the URL-to-filename translation hook which is used after the HTTP request was read and before any authorization starts and the Fixup hook which is triggered after the authorization phases and after the per-directory config files (
.htaccess
) where read, but before the content handler is activated.So, after a request comes in and Apache has determined the corresponding server (or virtual server) the rewriting engine start processing of all mod_rewrite directives from the per-server configuration in the URL-to-filename phase. A few steps later when the final data directories are found, the per-directory configuration directives of mod_rewrite are triggered in the Fixup phase. In both situations mod_rewrite either rewrites URLs to new URLs or to filenames, although there is no obvious distinction between them. This is a usage of the API which was not intended this way when the API was designed, but as of Apache 1.x this is the only way mod_rewrite can operate. To make this point more clear remember the following two points:
- The API currently provides only a URL-to-filename hook. Although mod_rewrite rewrites URLs to URLs, URLs to filenames and even filenames to filenames. In Apache 2.0 the two missing hooks will be added to make the processing more clear. But this point has no drawbacks for the user, it is just a fact which should be remembered: Apache does more in the URL-to-filename hook then the API intends for it.
- Unbelievably mod_rewrite provides URL manipulations in per-directory context, i.e. within
.htaccess
files, although these are reached a very long time after the URLs were translated to filenames (this has to be this way, because.htaccess
files stay in the filesystem, so processing has already been reached this stage of processing). In other words: According to the API phases at this time it is too late for any URL manipulations. To overcome this chicken and egg problem mod_rewrite uses a trick: When you manipulate a URL/filename in per-directory context mod_rewrite first rewrites the filename back to its corresponding URL (which it usually impossible, but see theRewriteBase
directive below for the trick to achieve this) and then initiates a new internal sub-request with the new URL. This leads to a new processing of the API phases from the beginning.Again mod_rewrite tries hard to make this complicated step totally transparent to the user, but you should remember here: While URL manipulations in per-server context are really fast and efficient, per-directory rewrites are slow and inefficient due to this chicken and egg problem. But on the other hand this is the only way mod_rewrite can provide (locally restricted) URL manipulations to the average user.
Don't forget these two points!
Ruleset Processing
Now when mod_rewrite is triggered in these two API phases, it reads the configured rulesets from its configuration structure (which itself was either created on startup for per-server context or while the directory walk of the Apache kernel for per-directory context). Then the URL rewriting engine is started with the contained ruleset (one or more rules together with their conditions). The operation of the URL rewriting engine itself is exactly the same for both configuration contexts. Just the final result processing is different.The order of rules in the ruleset is important because the rewriting engine processes them in a special order. And this order is not very obvious. The rule is this: The rewriting engine loops through the ruleset rule by rule (
RewriteRule
directives!) and when a particular rule matched it optionally loops through existing corresponding conditions (RewriteCond
directives). Because of h