|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"><head>
|
|
Packit |
90a5c9 |
<meta content="text/html; charset=ISO-8859-1" http-equiv="Content-Type" />
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
|
Packit |
90a5c9 |
This file is generated from xml source: DO NOT EDIT
|
|
Packit |
90a5c9 |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
|
Packit |
90a5c9 |
-->
|
|
Packit |
90a5c9 |
<title>Advanced Techniques with mod_rewrite - Apache HTTP Server Version 2.4</title>
|
|
Packit |
90a5c9 |
<link href="../style/css/manual.css" rel="stylesheet" media="all" type="text/css" title="Main stylesheet" />
|
|
Packit |
90a5c9 |
<link href="../style/css/manual-loose-100pc.css" rel="alternate stylesheet" media="all" type="text/css" title="No Sidebar - Default font size" />
|
|
Packit |
90a5c9 |
<link href="../style/css/manual-print.css" rel="stylesheet" media="print" type="text/css" /><link rel="stylesheet" type="text/css" href="../style/css/prettify.css" />
|
|
Packit |
90a5c9 |
<script src="../style/scripts/prettify.min.js" type="text/javascript">
|
|
Packit |
90a5c9 |
</script>
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
<link href="../images/favicon.ico" rel="shortcut icon" /></head>
|
|
Packit |
90a5c9 |
<body id="manual-page">
|
|
Packit |
90a5c9 |
Modules | Directives | FAQ | Glossary | Sitemap
|
|
Packit |
90a5c9 |
Apache HTTP Server Version 2.4
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
Apache > HTTP Server > Documentation > Version 2.4 > RewriteAdvanced Techniques with mod_rewrite
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
Available Languages: en |
|
|
Packit |
90a5c9 |
fr
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
This document supplements the mod_rewrite
|
|
Packit |
90a5c9 |
reference documentation. It provides
|
|
Packit |
90a5c9 |
a few advanced techniques using mod_rewrite.
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
Note that many of these examples won't work unchanged in your
|
|
Packit |
90a5c9 |
particular server configuration, so it's important that you understand
|
|
Packit |
90a5c9 |
them, rather than merely cutting and pasting the examples into your
|
|
Packit |
90a5c9 |
configuration.
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
On-the-fly Content-Regeneration
|
|
Packit |
90a5c9 |
Load Balancing
|
|
Packit |
90a5c9 |
Structured Userdirs
|
|
Packit |
90a5c9 |
Redirecting Anchors
|
|
Packit |
90a5c9 |
Time-Dependent Rewriting
|
|
Packit |
90a5c9 |
Set Environment Variables Based On URL Parts
|
|
Packit |
90a5c9 |
See also
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
Description:
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
A common technique for distributing the burden of
|
|
Packit |
90a5c9 |
server load or storage space is called "sharding".
|
|
Packit |
90a5c9 |
When using this method, a front-end server will use the
|
|
Packit |
90a5c9 |
url to consistently "shard" users or objects to separate
|
|
Packit |
90a5c9 |
backend servers.
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
Solution:
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
A mapping is maintained, from users to target servers, in
|
|
Packit |
90a5c9 |
external map files. They look like:
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
user1 physical_host_of_user1
|
|
Packit |
90a5c9 |
user2 physical_host_of_user2
|
|
Packit |
90a5c9 |
: :
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
We put this into a map.users-to-hosts file. The
|
|
Packit |
90a5c9 |
aim is to map;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
/u/user1/anypath
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
to
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
http://physical_host_of_user1/u/user/anypath
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
thus every URL path need not be valid on every backend physical
|
|
Packit |
90a5c9 |
host. The following ruleset does this for us with the help of the map
|
|
Packit |
90a5c9 |
files assuming that server0 is a default server which will be used if
|
|
Packit |
90a5c9 |
a user has no entry in the map:
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
RewriteEngine on
|
|
Packit |
90a5c9 |
RewriteMap users-to-hosts "txt:/path/to/map.users-to-hosts"
|
|
Packit |
90a5c9 |
RewriteRule "^/u/([^/]+)/?(.*)" "http://${users-to-hosts:$1|server0}/u/$1/$2"
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
See the RewriteMap
|
|
Packit |
90a5c9 |
documentation for more discussion of the syntax of this directive.
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
Description:
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
We wish to dynamically generate content, but store it
|
|
Packit |
90a5c9 |
statically once it is generated. This rule will check for the
|
|
Packit |
90a5c9 |
existence of the static file, and if it's not there, generate
|
|
Packit |
90a5c9 |
it. The static files can be removed periodically, if desired (say,
|
|
Packit |
90a5c9 |
via cron) and will be regenerated on demand.
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
Solution:
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
This is done via the following ruleset:
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
# This example is valid in per-directory context only
|
|
Packit |
90a5c9 |
RewriteCond "%{REQUEST_URI}" "!-U"
|
|
Packit |
90a5c9 |
RewriteRule "^(.+)\.html$" "/regenerate_page.cgi" [PT,L]
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
The -U operator determines whether the test string
|
|
Packit |
90a5c9 |
(in this case, REQUEST_URI ) is a valid URL. It does
|
|
Packit |
90a5c9 |
this via a subrequest. In the event that this subrequest fails -
|
|
Packit |
90a5c9 |
that is, the requested resource doesn't exist - this rule invokes
|
|
Packit |
90a5c9 |
the CGI program /regenerate_page.cgi , which generates
|
|
Packit |
90a5c9 |
the requested resource and saves it into the document directory, so
|
|
Packit |
90a5c9 |
that the next time it is requested, a static copy can be served.
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
In this way, documents that are infrequently updated can be served in
|
|
Packit |
90a5c9 |
static form. if documents need to be refreshed, they can be deleted
|
|
Packit |
90a5c9 |
from the document directory, and they will then be regenerated the
|
|
Packit |
90a5c9 |
next time they are requested.
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
Description:
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
We wish to randomly distribute load across several servers
|
|
Packit |
90a5c9 |
using mod_rewrite.
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
Solution:
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
We'll use RewriteMap and a list of servers
|
|
Packit |
90a5c9 |
to accomplish this.
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
RewriteEngine on
|
|
Packit |
90a5c9 |
RewriteMap lb "rnd:/path/to/serverlist.txt"
|
|
Packit |
90a5c9 |
RewriteRule "^/(.*)" "http://${lb:servers}/$1" [P,L]
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
serverlist.txt will contain a list of the servers:
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
## serverlist.txt
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
servers one.example.com|two.example.com|three.example.com
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
If you want one particular server to get more of the load than the
|
|
Packit |
90a5c9 |
others, add it more times to the list.
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
Discussion
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
Apache comes with a load-balancing module -
|
|
Packit |
90a5c9 |
mod_proxy_balancer - which is far more flexible and
|
|
Packit |
90a5c9 |
featureful than anything you can cobble together using mod_rewrite.
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
Description:
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
Some sites with thousands of users use a
|
|
Packit |
90a5c9 |
structured homedir layout, i.e. each homedir is in a
|
|
Packit |
90a5c9 |
subdirectory which begins (for instance) with the first
|
|
Packit |
90a5c9 |
character of the username. So, /~larry/anypath
|
|
Packit |
90a5c9 |
is /home/l/larry/public_html/anypath
|
|
Packit |
90a5c9 |
while /~waldo/anypath is
|
|
Packit |
90a5c9 |
/home/w/waldo/public_html/anypath .
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
Solution:
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
We use the following ruleset to expand the tilde URLs
|
|
Packit |
90a5c9 |
into the above layout.
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
RewriteEngine on
|
|
Packit |
90a5c9 |
RewriteRule "^/~(([a-z])[a-z0-9]+)(.*)" "/home/$2/$1/public_html$3"
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
Description:
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
By default, redirecting to an HTML anchor doesn't work,
|
|
Packit |
90a5c9 |
because mod_rewrite escapes the # character,
|
|
Packit |
90a5c9 |
turning it into %23 . This, in turn, breaks the
|
|
Packit |
90a5c9 |
redirection.
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
Solution:
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
Use the [NE] flag on the
|
|
Packit |
90a5c9 |
RewriteRule . NE stands for No Escape.
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
Discussion:
|
|
Packit |
90a5c9 |
This technique will of course also work with other
|
|
Packit |
90a5c9 |
special characters that mod_rewrite, by default, URL-encodes.
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
Description:
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
We wish to use mod_rewrite to serve different content based on
|
|
Packit |
90a5c9 |
the time of day.
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
Solution:
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
There are a lot of variables named TIME_xxx
|
|
Packit |
90a5c9 |
for rewrite conditions. In conjunction with the special
|
|
Packit |
90a5c9 |
lexicographic comparison patterns <STRING ,
|
|
Packit |
90a5c9 |
>STRING and =STRING we can
|
|
Packit |
90a5c9 |
do time-dependent redirects:
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
RewriteEngine on
|
|
Packit |
90a5c9 |
RewriteCond "%{TIME_HOUR}%{TIME_MIN}" ">0700"
|
|
Packit |
90a5c9 |
RewriteCond "%{TIME_HOUR}%{TIME_MIN}" "<1900"
|
|
Packit |
90a5c9 |
RewriteRule "^foo\.html$" "foo.day.html" [L]
|
|
Packit |
90a5c9 |
RewriteRule "^foo\.html$" "foo.night.html"
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
This provides the content of foo.day.html
|
|
Packit |
90a5c9 |
under the URL foo.html from
|
|
Packit |
90a5c9 |
07:01-18:59 and at the remaining time the
|
|
Packit |
90a5c9 |
contents of foo.night.html .
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
and browsers may each cache responses and cause the either page to be
|
|
Packit |
90a5c9 |
shown outside of the time-window configured.
|
|
Packit |
90a5c9 |
mod_expires may be used to control this
|
|
Packit |
90a5c9 |
effect. You are, of course, much better off simply serving the
|
|
Packit |
90a5c9 |
content dynamically, and customizing it based on the time of day.
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
Description:
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
At time, we want to maintain some kind of status when we
|
|
Packit |
90a5c9 |
perform a rewrite. For example, you want to make a note that
|
|
Packit |
90a5c9 |
you've done that rewrite, so that you can check later to see if a
|
|
Packit |
90a5c9 |
request can via that rewrite. One way to do this is by setting an
|
|
Packit |
90a5c9 |
environment variable.
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
Solution:
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
Use the [E] flag to set an environment variable.
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
RewriteEngine on
|
|
Packit |
90a5c9 |
RewriteRule "^/horse/(.*)" "/pony/$1" [E=rewritten:1]
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
Later in your ruleset you might check for this environment
|
|
Packit |
90a5c9 |
variable using a RewriteCond:
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
RewriteCond "%{ENV:rewritten}" "=1"
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
Note that environment variables do not survive an external
|
|
Packit |
90a5c9 |
redirect. You might consider using the [CO] flag to set a
|
|
Packit |
90a5c9 |
cookie.
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
Available Languages: en |
|
|
Packit |
90a5c9 |
fr
|
|
Packit |
90a5c9 |
Notice:This is not a Q&A section. Comments placed here should be pointed towards suggestions on improving the documentation or server, and may be removed again by our moderators if they are either implemented or considered invalid/off-topic. Questions on how to manage the Apache HTTP Server should be directed at either our IRC channel, #httpd, on Freenode, or sent to our mailing lists.
|
|
Packit |
90a5c9 |
<script type="text/javascript">
|
|
Packit |
90a5c9 |
var comments_shortname = 'httpd';
|
|
Packit |
90a5c9 |
var comments_identifier = 'http://httpd.apache.org/docs/2.4/rewrite/advanced.html';
|
|
Packit |
90a5c9 |
(function(w, d) {
|
|
Packit |
90a5c9 |
if (w.location.hostname.toLowerCase() == "httpd.apache.org") {
|
|
Packit |
90a5c9 |
d.write('
|
|
Packit |
90a5c9 |
var s = d.createElement('script');
|
|
Packit |
90a5c9 |
s.type = 'text/javascript';
|
|
Packit |
90a5c9 |
s.async = true;
|
|
Packit |
90a5c9 |
s.src = 'https://comments.apache.org/show_comments.lua?site=' + comments_shortname + '&page=' + comments_identifier;
|
|
Packit |
90a5c9 |
(d.getElementsByTagName('head')[0] || d.getElementsByTagName('body')[0]).appendChild(s);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
else {
|
|
Packit |
90a5c9 |
d.write('
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
})(window, document);
|
|
Packit |
90a5c9 |
//--></script>
|
|
Packit |
90a5c9 |
Copyright 2018 The Apache Software Foundation. Licensed under the Apache License, Version 2.0.
|
|
Packit |
90a5c9 |
Modules | Directives | FAQ | Glossary | Sitemap <script type="text/javascript">
|
|
Packit |
90a5c9 |
if (typeof(prettyPrint) !== 'undefined') {
|
|
Packit |
90a5c9 |
prettyPrint();
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
//--></script>
|
|
Packit |
90a5c9 |
</body></html>
|