apache mod_rewrite module guide - part 2
Apache Mod_Rewrite is a module for the Apache HTTP Server that allows for the rewriting of URL requests that come into the server. It provides a way to use rule-based rewriting logic to change the requested URL’s appearance, control the flow of requests, and redirect URLs based on specific conditions.
RewriteBase Directive
- Description: Sets the base URL for per-directory rewrites
- Syntax: RewriteBase URL-path
- Default: None
- Context: directory, .htaccess
- Override: FileInfo
- Status: Extension
- Module: mod_rewrite
RewriteBase is used to fix cases where mod_rewrite is running in a per-directory context (Directory
or .htaccess
)
There it will act locally, i.e., the local directory prefix is stripped at this stage of processing and your rewriting rules act only on the remainder. At the end it is automatically added back to the 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. But at most websites URLs are NOT directly related to physical filename paths, so this assumption will usually be wrong! There you have to use the RewriteBase
directive to specify the correct URL-prefix.
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.
Note - 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 the correct Apache internal processing, because the per-directory rewriting comes too late in the process. So, when it occurs the (rewritten) request has to be re-injected into the Apache kernel! BUT: While this seems like a serious overhead, it really isn't, because this re-injection happens fully internally to the Apache server and the same procedure is used by many other operations inside Apache. So, you can be sure the design and implementation is correct.
Debugging rewrites on Apache 2.4
In Apache 2.4, the RewriteLog
and RewriteLogLevel
on mod_rewrite level are replaced by LogLevel
on core level which you can configure for all modules. See the Apache documentation for detailed information:
Note that the Redirect directive is part mod_alias and not of mod_rewrite. So make sure you are looking for the right logging information. While mod_rewrite offers detailed logging of its actions at the trace1 to trace8 log levels, mod_alias unfortunately does not have this.
Enable logging for mod_rewrite and mod_alias:
LogLevel alert rewrite:trace3 alias:debug
mod_rewrite
For a redirect like this:
RewriteEngine On
RewriteRule /foo /bar [R=301,L]
You will see logging information in error.log file like this:
mod_rewrite.c(477): [www.mybluelinux.com/sid#7f70e2d393f0][rid#7f70e2bec0a0/initial] init rewrite engine with requested uri /foo/
mod_rewrite.c(477): [www.mybluelinux.com/sid#7f70e2d393f0][rid#7f70e2bec0a0/initial] applying pattern '/foo' to uri '/foo/'
mod_rewrite.c(477): [www.mybluelinux.com/sid#7f70e2d393f0][rid#7f70e2bec0a0/initial] rewrite '/foo/' -> '/bar'
mod_rewrite.c(477): [www.mybluelinux.com/sid#7f70e2d393f0][rid#7f70e2bec0a0/initial] explicitly forcing redirect with https://www.mybluelinux.com/bar
mod_rewrite.c(477): [www.mybluelinux.com/sid#7f70e2d393f0][rid#7f70e2bec0a0/initial] escaping https://www.mybluelinux.com/bar for redirect
mod_rewrite.c(477): [www.mybluelinux.com/sid#7f70e2d393f0][rid#7f70e2bec0a0/initial] redirect to https://www.mybluelinux.com/bar [REDIRECT/301]
mod_rewrite.c(477): [www.mybluelinux.com/sid#7f70e2d393f0][rid#7f70e2bea0a0/initial] init rewrite engine with requested uri /bar
mod_rewrite.c(477): [www.mybluelinux.com/sid#7f70e2d393f0][rid#7f70e2bea0a0/initial] applying pattern '/foo' to uri '/bar'
mod_rewrite.c(477): [www.mybluelinux.com/sid#7f70e2d393f0][rid#7f70e2bea0a0/initial] pass through /bar
mod_rewrite.c(477): [www.mybluelinux.com/sid#7f70e2d393f0][rid#7f70e2bec0a0/initial] init rewrite engine with requested uri /bar/
mod_rewrite.c(477): [www.mybluelinux.com/sid#7f70e2d393f0][rid#7f70e2bec0a0/initial] applying pattern '/foo' to uri '/bar/'
mod_rewrite.c(477): [www.mybluelinux.com/sid#7f70e2d393f0][rid#7f70e2bec0a0/initial] pass through /bar/
mod_rewrite.c(477): [www.mybluelinux.com/sid#7f70e2d393f0][rid#7f70e2be80a0/subreq] init rewrite engine with requested uri /bar/index.html
mod_rewrite.c(477): [www.mybluelinux.com/sid#7f70e2d393f0][rid#7f70e2be80a0/subreq] pass through /bar/index.html