<-
Apache > HTTP Server > Documentation > Version 2.2 > Modules

Apache Module mod_rewrite

Available Languages:  en 

Description:Provides a rule-based rewriting engine to rewrite requested URLs on the fly
Status:Extension
Module Identifier:rewrite_module
Source File:mod_rewrite.c
Compatibility:Available in Apache 1.3 and later

Summary

This 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, of server variables, environment variables, HTTP headers, or time stamps. Even external database lookups in various formats can be used to achieve highly 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 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.

Further details, discussion, and examples, are provided in the detailed mod_rewrite documentation.

Directives

Topics

top

Quoting Special Characters

As of Apache 1.3.20, special characters in TestString and Substitution strings can be escaped (that is, treated as normal characters without their usual special meaning) by prefixing them with a slash ('\') character. In other words, you can include an actual dollar-sign character in a Substitution string by using '\$'; this keeps mod_rewrite from trying to treat it as a backreference.

top

Environment Variables

This module keeps track of two additional (non-standard) CGI/SSI environment variables named SCRIPT_URL and SCRIPT_URI. These contain the logical Web-view to the current resource, while the standard CGI/SSI variables SCRIPT_NAME and SCRIPT_FILENAME contain the physical System-view.

Notice: These variables hold the URI/URL as they were initially requested, that is, before any rewriting. This is important to note because the rewriting process is primarily used to rewrite logical URLs to physical pathnames.

Example

SCRIPT_NAME=/sw/lib/w3s/tree/global/u/rse/.www/index.html
SCRIPT_FILENAME=/u/rse/.www/index.html
SCRIPT_URL=/u/rse/
SCRIPT_URI=http://en1.engelschall.com/u/rse/
top

Practical Solutions

For numerous examples of common, and not-so-common, uses for mod_rewrite, see the Rewrite Guide, and the Advanced Rewrite Guide documents.

top

RewriteBase Directive

Description:Sets the base URL for per-directory rewrites
Syntax:RewriteBase URL-path
Default:See usage for information.
Context:directory, .htaccess
Override:FileInfo
Status:Extension
Module:mod_rewrite

The RewriteBase directive explicitly sets the base URL for per-directory rewrites. As you will see below, RewriteRule can be used in per-directory config files (.htaccess). In such a case, it will act locally, stripping the local directory prefix before processing, and applying rewrite rules only to the remainder. When processing is complete, the prefix is automatically added back to the path. The default setting is; RewriteBase physical-directory-path

When a substitution occurs for a new URL, this module has to re-inject the URL into the server processing. To be able to do this it needs to know what the corresponding URL-prefix or URL-base is. By default this prefix is the corresponding filepath itself. However, for most websites, URLs are NOT directly related to physical filename paths, so this assumption will often be wrong! Therefore, you can use the RewriteBase directive to specify the correct URL-prefix.

If your webserver's URLs are not directly related to physical file paths, you will need to use RewriteBase in every .htaccess file where you want to use RewriteRule directives.

For example, assume the following per-directory config file:

#
#  /abc/def/.htaccess -- per-dir config file for directory /abc/def
#  Remember: /abc/def is the physical path of /xyz, i.e., the server
#            has a 'Alias /xyz /abc/def' directive e.g.
#

RewriteEngine On

#  let the server know that we were reached via /xyz and not
#  via the physical path prefix /abc/def
RewriteBase   /xyz

#  now the rewriting rules
RewriteRule   ^oldstuff\.html$  newstuff.html

In the above example, a request to /xyz/oldstuff.html gets correctly rewritten to the physical file /abc/def/newstuff.html.

For Apache Hackers

The following list gives detailed information about the internal processing steps:

Request:
  /xyz/oldstuff.html

Internal Processing:
  /xyz/oldstuff.html     -> /abc/def/oldstuff.html  (per-server Alias)
  /abc/def/oldstuff.html -> /abc/def/newstuff.html  (per-dir    RewriteRule)
  /abc/def/newstuff.html -> /xyz/newstuff.html      (per-dir    RewriteBase)
  /xyz/newstuff.html     -> /abc/def/newstuff.html  (per-server Alias)

Result:
  /abc/def/newstuff.html

This seems very complicated, but is in fact correct Apache internal processing. Because the per-directory rewriting comes late in the process, the rewritten request has to be re-injected into the Apache kernel. This is not the serious overhead it may seem to be - this re-injection is completely internal to the Apache server (and the same procedure is used by many other operations within Apache).

top

RewriteCond Directive

Description:Defines a condition under which rewriting will take place
Syntax: RewriteCond TestString CondPattern
Context:server config, virtual host, directory, .htaccess
Override:FileInfo
Status:Extension
Module:mod_rewrite

The RewriteCond directive defines a rule condition. One or more RewriteCond can precede a RewriteRule directive. The following rule is then only used if both the current state of the URI matches its pattern, and if these conditions are met.

TestString is a string which can contain the following expanded constructs in addition to plain text:

Other things you should be aware of:

  1. The variables SCRIPT_FILENAME and REQUEST_FILENAME contain the same value - the value of the filename field of the internal request_rec structure of the Apache server. The first name is the commonly known CGI variable name while the second is the appropriate counterpart of REQUEST_URI (which contains the value of the uri field of request_rec).
  2. %{ENV:variable}, where variable can be any environment variable, is also available. This is looked-up via internal Apache structures and (if not found there) via getenv() from the Apache server process.
  3. %{SSL:variable}, where variable is the name of an SSL environment variable, can be used whether or not mod_ssl is loaded, but will always expand to the empty string if it is not. Example: %{SSL:SSL_CIPHER_USEKEYSIZE} may expand to 128.
  4. %{HTTP:header}, where header can be any HTTP MIME-header name, can always be used to obtain the value of a header sent in the HTTP request. Example: %{HTTP:Proxy-Connection} is the value of the HTTP header ``Proxy-Connection:''.
  5. %{LA-U:variable} can be used for look-aheads which perform an internal (URL-based) sub-request to determine the final value of variable. This can be used to access variable for rewriting which is not available at the current stage, but will be set in a later phase.

    For instance, to rewrite according to the REMOTE_USER variable from within the per-server context (httpd.conf file) you must use %{LA-U:REMOTE_USER} - this variable is set by the authorization phases, which come after the URL translation phase (during which mod_rewrite operates).

    On the other hand, because mod_rewrite implements its per-directory context (.htaccess file) via the Fixup phase of the API and because the authorization phases come before this phase, you just can use %{REMOTE_USER} in that context.

  6. %{LA-F:variable} can be used to perform an internal (filename-based) sub-request, to determine the final value of variable. Most of the time, this is the same as LA-U above.

CondPattern is the condition pattern, a regular expression which is applied to the current instance of the TestString. TestString is first evaluated, before being matched against CondPattern.

Remember: CondPattern is a perl compatible regular expression with some additions:

  1. You can prefix the pattern string with a '!' character (exclamation mark) to specify a non-matching pattern.
  2. There are some special variants of CondPatterns. Instead of real regular expression strings you can also use one of the following:
    • '<CondPattern' (lexicographically precedes)
      Treats the CondPattern as a plain string and compares it lexicographically to TestString. True if TestString lexicographically precedes CondPattern.
    • '>CondPattern' (lexicographically follows)
      Treats the CondPattern as a plain string and compares it lexicographically to TestString. True if TestString lexicographically follows CondPattern.
    • '=CondPattern' (lexicographically equal)
      Treats the CondPattern as a plain string and compares it lexicographically to TestString. True if TestString is lexicographically equal to CondPattern (the two strings are exactly equal, character for character). If CondPattern is "" (two quotation marks) this compares TestString to the empty string.
    • '-d' (is directory)
      Treats the TestString as a pathname and tests whether or not it exists, and is a directory.
    • '-f' (is regular file)
      Treats the TestString as a pathname and tests whether or not it exists, and is a regular file.
    • '-s' (is regular file, with size)
      Treats the TestString as a pathname and tests whether or not it exists, and is a regular file with size greater than zero.
    • '-l' (is symbolic link)
      Treats the TestString as a pathname and tests whether or not it exists, and is a symbolic link.
    • '-x' (has executable permissions)
      Treats the TestString as a pathname and tests whether or not it exists, and has executable permissions. These permissions are determined according to the underlying OS.
    • '-F' (is existing file, via subrequest)
      Checks whether or not TestString is a valid file, accessible via all the server's currently-configured access controls for that path. This uses an internal subrequest to do the check, so use it with care - it can impact your server's performance!
    • '-U' (is existing URL, via subrequest)
      Checks whether or not TestString is a valid URL, accessible via all the server's currently-configured access controls for that path. This uses an internal subrequest to do the check, so use it with care - it can impact your server's performance!

    Note:

    All of these tests can also be prefixed by an exclamation mark ('!') to negate their meaning.
  3. You can also set special flags for CondPattern by appending [flags] as the third argument to the RewriteCond directive, where flags is a comma-separated list of any of the following flags:
    • 'nocase|NC' (no case)
      This makes the test case-insensitive - differences between 'A-Z' and 'a-z' are ignored, both in the expanded TestString and the CondPattern. This flag is effective only for comparisons between TestString and CondPattern. It has no effect on filesystem and subrequest checks.
    • 'ornext|OR' (or next condition)
      Use this to combine rule conditions with a local OR instead of the implicit AND. Typical example:
      RewriteCond %{REMOTE_HOST}  ^host1.*  [OR]
      RewriteCond %{REMOTE_HOST}  ^host2.*  [OR]
      RewriteCond %{REMOTE_HOST}  ^host3.*
      RewriteRule ...some special stuff for any of these hosts...
      
      Without this flag you would have to write the condition/rule pair three times.

Example:

To rewrite the Homepage of a site according to the ``User-Agent:'' header of the request, you can use the following:

RewriteCond  %{HTTP_USER_AGENT}  ^Mozilla.*
RewriteRule  ^/$                 /homepage.max.html  [L]

RewriteCond  %{HTTP_USER_AGENT}  ^Lynx.*
RewriteRule  ^/$                 /homepage.min.html  [L]

RewriteRule  ^/$                 /homepage.std.html  [L]

Explanation: If you use a browser which identifies itself as 'Mozilla' (including Netscape Navigator, Mozilla etc), then you get the max homepage (which could include frames, or other special features). If you use the Lynx browser (which is terminal-based), then you get the min homepage (which could be a version designed for easy, text-only browsing). If neither of these conditions apply (you use any other browser, or your browser identifies itself as something non-standard), you get the std (standard) homepage.

top

RewriteEngine Directive

Description:Enables or disables runtime rewriting engine
Syntax:RewriteEngine on|off
Default:RewriteEngine off
Context:server config, virtual host, directory, .htaccess
Override:FileInfo
Status:Extension
Module:mod_rewrite

The RewriteEngine directive enables or disables the runtime rewriting engine. If it is set to off this module does no runtime processing at all. It does not even update the SCRIPT_URx environment variables.

Use this directive to disable the module instead of commenting out all the RewriteRule directives!

Note that, by default, rewrite configurations are not inherited. This means that you need to have a RewriteEngine on directive for each virtual host in which you wish to use it.

top

RewriteLock Directive

Description:Sets the name of the lock file used for RewriteMap synchronization
Syntax:RewriteLock file-path
Context:server config
Status:Extension
Module:mod_rewrite

This directive sets the filename for a synchronization lockfile which mod_rewrite needs to communicate with RewriteMap programs. Set this lockfile to a local path (not on a NFS-mounted device) when you want to use a rewriting map-program. It is not required for other types of rewriting maps.

top

RewriteLog Directive

Description:Sets the name of the file used for logging rewrite engine processing
Syntax:RewriteLog file-path
Context:server config, virtual host
Status:Extension
Module:mod_rewrite

The RewriteLog directive sets the name of the file to which the server logs any rewriting actions it performs. If the name does not begin with a slash ('/') then it is assumed to be relative to the Server Root. The directive should occur only once per server config.

To disable the logging of rewriting actions it is not recommended to set Filename to /dev/null, because although the rewriting engine does not then output to a logfile it still creates the logfile output internally. This will slow down the server with no advantage to the administrator! To disable logging either remove or comment out the RewriteLog directive or use RewriteLogLevel 0!

Security

See the Apache Security Tips document for details on how your security could be compromised if the directory where logfiles are stored is writable by anyone other than the user that starts the server.

Example

RewriteLog "/usr/local/var/apache/logs/rewrite.log"

top

RewriteLogLevel Directive

Description:Sets the verbosity of the log file used by the rewrite engine
Syntax:RewriteLogLevel Level
Default:RewriteLogLevel 0
Context:server config, virtual host
Status:Extension
Module:mod_rewrite

The RewriteLogLevel directive sets the verbosity level of the rewriting logfile. The default level 0 means no logging, while 9 or more means that practically all actions are logged.

To disable the logging of rewriting actions simply set Level to 0. This disables all rewrite action logs.

Using a high value for Level will slow down your Apache server dramatically! Use the rewriting logfile at a Level greater than 2 only for debugging!

Example

RewriteLogLevel 3

top

RewriteMap Directive

Description:Defines a mapping function for key-lookup
Syntax:RewriteMap MapName MapType:MapSource
Context:server config, virtual host
Status:Extension
Module:mod_rewrite
Compatibility:The choice of different dbm types is available in Apache 2.0.41 and later

The RewriteMap directive defines a Rewriting Map which can be used inside rule substitution strings by the mapping-functions to insert/substitute fields through a key lookup. The source of this lookup can be of various types.

The MapName is the name of the map and will be used to specify a mapping-function for the substitution strings of a rewriting rule via one of the following constructs:

${ MapName : LookupKey }
${ MapName : LookupKey | DefaultValue }

When such a construct occurs, the map MapName is consulted and the key LookupKey is looked-up. If the key is found, the map-function construct is substituted by SubstValue. If the key is not found then it is substituted by DefaultValue or by the empty string if no DefaultValue was specified.

For example, you might define a RewriteMap as:

RewriteMap examplemap txt:/path/to/file/map.txt

You would then be able to use this map in a RewriteRule as follows:

RewriteRule ^/ex/(.*) ${examplemap:$1}

The following combinations for MapType and MapSource can be used:

The RewriteMap directive can occur more than once. For each mapping-function use one RewriteMap directive to declare its rewriting mapfile. While you cannot declare a map in per-directory context it is of course possible to use this map in per-directory context.

Note

For plain text and DBM format files the looked-up keys are cached in-core until the mtime of the mapfile changes or the server does a restart. This way you can have map-functions in rules which are used for every request. This is no problem, because the external lookup only happens once!
top

RewriteOptions Directive

Description:Sets some special options for the rewrite engine
Syntax:RewriteOptions Options
Context:server config, virtual host, directory, .htaccess
Override:FileInfo
Status:Extension
Module:mod_rewrite
Compatibility:MaxRedirects is no longer available in version 2.1 and later

The RewriteOptions directive sets some special options for the current per-server or per-directory configuration. The Option string can currently only be one of the following:

inherit
This forces the current configuration to inherit the configuration of the parent. In per-virtual-server context, this means that the maps, conditions and rules of the main server are inherited. In per-directory context this means that conditions and rules of the parent directory's .htaccess configuration are inherited.
top

RewriteRule Directive

Description:Defines rules for the rewriting engine
Syntax:RewriteRule Pattern Substitution
Context:server config, virtual host, directory, .htaccess
Override:FileInfo
Status:Extension
Module:mod_rewrite
Compatibility:The cookie-flag is available in Apache 2.0.40 and later.

The RewriteRule directive is the real rewriting workhorse. The directive can occur more than once, with each instance defining a single rewrite rule. The order in which these rules are defined is important - this is the order in which they will be applied at run-time.

Pattern is a perl compatible regular expression, which is applied to the current URL. ``Current'' means the value of the URL when this rule is applied. This may not be the originally requested URL, which may already have matched a previous rule, and have been altered.

Some hints on the syntax of regular expressions:

Text:
  .           Any single character
  [chars]     Character class: Any character of the class ``chars''
  [^chars]    Character class: Not a character of the class ``chars''
  text1|text2 Alternative: text1 or text2

Quantifiers:
  ?           0 or 1 occurrences of the preceding text
  *           0 or N occurrences of the preceding text (N > 0)
  +           1 or N occurrences of the preceding text (N > 1)

Grouping:
  (text)      Grouping of text
              (used either to set the borders of an alternative as above, or
              to make backreferences, where the Nth group can 
              be referred to on the RHS of a RewriteRule as $N)

Anchors:
  ^           Start-of-line anchor
  $           End-of-line anchor

Escaping:
  \char       escape the given char
              (for instance, to specify the chars ".[]()" etc.)

For more information about regular expressions, have a look at the perl regular expression manpage ("perldoc perlre"). If you are interested in more detailed information about regular expressions and their variants (POSIX regex etc.) the following book is dedicated to this topic:

Mastering Regular Expressions, 2nd Edition
Jeffrey E.F. Friedl
O'Reilly & Associates, Inc. 2002
ISBN 0-596-00289-0

In mod_rewrite, the NOT character ('!') is also available as a possible pattern prefix. This enables you to negate a pattern; to say, for instance: ``if the current URL does NOT match this pattern''. This can be used for exceptional cases, where it is easier to match the negative pattern, or as a last default rule.

Note

When using the NOT character to negate a pattern, you cannot include grouped wildcard parts in that pattern. This is because, when the pattern does NOT match (ie, the negation matches), there are no contents for the groups. Thus, if negated patterns are used, you cannot use $N in the substitution string!

The substitution of a rewrite rule is the string which is substituted for (or replaces) the original URL which Pattern matched. In addition to plain text, it can include

  1. back-references ($N) to the RewriteRule pattern
  2. back-references (%N) to the last matched RewriteCond pattern
  3. server-variables as in rule condition test-strings (%{VARNAME})
  4. mapping-function calls (${mapname:key|default})

Back-references are identifiers of the form $N (N=0..9), which will be replaced by the contents of the Nth group of the matched Pattern. The server-variables are the same as for the TestString of a RewriteCond directive. The mapping-functions come from the RewriteMap directive and are explained there. These three types of variables are expanded in the order above.

As already mentioned, all rewrite rules are applied to the Substitution (in the order in which they are defined in the config file). The URL is completely replaced by the Substitution and the rewriting process continues until all rules have been applied, or it is explicitly terminated by a L flag.

There is a special substitution string named '-' which means: NO substitution! This is useful in providing rewriting rules which only match URLs but do not substitute anything for them. It is commonly used in conjunction with the C (chain) flag, in order to apply more than one pattern before substitution occurs.

Additionally you can set special flags for Substitution by appending [flags] as the third argument to the RewriteRule directive. Flags is a comma-separated list of any of the following flags:

Per-directory Rewrites

The rewrite engine may be used in .htaccess files. To enable the rewrite engine for these files you need to set "RewriteEngine On" and "Options FollowSymLinks" must be enabled. If your administrator has disabled override of FollowSymLinks for a user's directory, then you cannot use the rewrite engine. This restriction is required for security reasons.

When using the rewrite engine in .htaccess files the per-directory prefix (which always is the same for a specific directory) is automatically removed for the pattern matching and automatically added after the substitution has been done. This feature is essential for many sorts of rewriting; without this, you would always have to match the parent directory, which is not always possible. There is one exception: If a substitution string starts with http://, then the directory prefix will not be added, and an external redirect (or proxy throughput, if using flag P) is forced. See the RewriteBase directive for more information.

The rewrite engine may also be used in <Directory> sections with the same prefix-matching rules as would be applied to .htaccess files. It is usually simpler, however, to avoid the prefix substitution complication by putting the rewrite rules in the main server or virtual host context, rather than in a <Directory> section.

Although rewrite rules are syntactically permitted in <Location> sections, this should never be necessary and is unsupported.

Note: Substitution of Absolute URLs

When you prefix a substitution field with http://thishost[:thisport], mod_rewrite will automatically strip that out. This auto-reduction on URLs with an implicit external redirect is most useful in combination with a mapping-function which generates the hostname part.

Remember: An unconditional external redirect to your own server will not work with the prefix http://thishost because of this feature. To achieve such a self-redirect, you have to use the R-flag.

Note: Query String

The Pattern will not be matched against the query string. To do this, you must use a RewriteCond with the %{QUERY_STRING} variable. You can, however, create URLs in the substitution string, containing a query string part. Simply use a question mark inside the substitution string, to indicate that the following text should be re-injected into the query string. When you want to erase an existing query string, end the substitution string with just a question mark. To combine new and old query strings, use the [QSA] flag.

Here are all possible substitution combinations and their meanings:

Inside per-server configuration (httpd.conf)
for request ``GET /somepath/pathinfo'':

Given Rule                                      Resulting Substitution
----------------------------------------------  ----------------------------------
^/somepath(.*) otherpath$1                      invalid, not supported

^/somepath(.*) otherpath$1  [R]                 invalid, not supported

^/somepath(.*) otherpath$1  [P]                 invalid, not supported
----------------------------------------------  ----------------------------------
^/somepath(.*) /otherpath$1                     /otherpath/pathinfo

^/somepath(.*) /otherpath$1 [R]                 http://thishost/otherpath/pathinfo
                                                via external redirection

^/somepath(.*) /otherpath$1 [P]                 doesn't make sense, not supported
----------------------------------------------  ----------------------------------
^/somepath(.*) http://thishost/otherpath$1      /otherpath/pathinfo

^/somepath(.*) http://thishost/otherpath$1 [R]  http://thishost/otherpath/pathinfo
                                                via external redirection

^/somepath(.*) http://thishost/otherpath$1 [P]  doesn't make sense, not supported
----------------------------------------------  ----------------------------------
^/somepath(.*) http://otherhost/otherpath$1     http://otherhost/otherpath/pathinfo
                                                via external redirection

^/somepath(.*) http://otherhost/otherpath$1 [R] http://otherhost/otherpath/pathinfo
                                                via external redirection
                                                (the [R] flag is redundant)

^/somepath(.*) http://otherhost/otherpath$1 [P] http://otherhost/otherpath/pathinfo
                                                via internal proxy

Inside per-directory configuration for /somepath
(/physical/path/to/somepath/.htacccess, with RewriteBase /somepath)
for request ``GET /somepath/localpath/pathinfo'':

Given Rule                                      Resulting Substitution
----------------------------------------------  ----------------------------------
^localpath(.*) otherpath$1                      /somepath/otherpath/pathinfo

^localpath(.*) otherpath$1  [R]                 http://thishost/somepath/otherpath/pathinfo
                                                via external redirection

^localpath(.*) otherpath$1  [P]                 doesn't make sense, not supported
----------------------------------------------  ----------------------------------
^localpath(.*) /otherpath$1                     /otherpath/pathinfo

^localpath(.*) /otherpath$1 [R]                 http://thishost/otherpath/pathinfo
                                                via external redirection

^localpath(.*) /otherpath$1 [P]                 doesn't make sense, not supported
----------------------------------------------  ----------------------------------
^localpath(.*) http://thishost/otherpath$1      /otherpath/pathinfo

^localpath(.*) http://thishost/otherpath$1 [R]  http://thishost/otherpath/pathinfo
                                                via external redirection

^localpath(.*) http://thishost/otherpath$1 [P]  doesn't make sense, not supported
----------------------------------------------  ----------------------------------
^localpath(.*) http://otherhost/otherpath$1     http://otherhost/otherpath/pathinfo
                                                via external redirection

^localpath(.*) http://otherhost/otherpath$1 [R] http://otherhost/otherpath/pathinfo
                                                via external redirection
                                                (the [R] flag is redundant)

^localpath(.*) http://otherhost/otherpath$1 [P] http://otherhost/otherpath/pathinfo
                                                via internal proxy

Available Languages:  en