1<?xml version="1.0" encoding="UTF-8"?>
2<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
3<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"><head>
4<meta content="text/html; charset=UTF-8" http-equiv="Content-Type" />
5<!--
6        XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
7              This file is generated from xml source: DO NOT EDIT
8        XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
9      -->
10<title>Advanced Techniques with mod_rewrite - Apache HTTP Server Version 2.4</title>
11<link href="../style/css/manual.css" rel="stylesheet" media="all" type="text/css" title="Main stylesheet" />
12<link href="../style/css/manual-loose-100pc.css" rel="alternate stylesheet" media="all" type="text/css" title="No Sidebar - Default font size" />
13<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" />
14<script src="../style/scripts/prettify.min.js" type="text/javascript">
15</script>
16
17<link href="../images/favicon.ico" rel="shortcut icon" /></head>
18<body id="manual-page"><div id="page-header">
19<p class="menu"><a href="../mod/">Modules</a> | <a href="../mod/directives.html">Directives</a> | <a href="http://wiki.apache.org/httpd/FAQ">FAQ</a> | <a href="../glossary.html">Glossary</a> | <a href="../sitemap.html">Sitemap</a></p>
20<p class="apache">Apache HTTP Server Version 2.4</p>
21<img alt="" src="../images/feather.png" /></div>
22<div class="up"><a href="./"><img title="&lt;-" alt="&lt;-" src="../images/left.gif" /></a></div>
23<div id="path">
24<a href="http://www.apache.org/">Apache</a> &gt; <a href="http://httpd.apache.org/">HTTP Server</a> &gt; <a href="http://httpd.apache.org/docs/">Documentation</a> &gt; <a href="../">Version 2.4</a> &gt; <a href="./">Rewrite</a></div><div id="page-content"><div id="preamble"><h1>Advanced Techniques with mod_rewrite</h1>
25<div class="toplang">
26<p><span>Available Languages: </span><a href="../en/rewrite/advanced.html" title="English">&nbsp;en&nbsp;</a> |
27<a href="../fr/rewrite/advanced.html" hreflang="fr" rel="alternate" title="Français">&nbsp;fr&nbsp;</a></p>
28</div>
29
30
31<p>This document supplements the <code class="module"><a href="../mod/mod_rewrite.html">mod_rewrite</a></code>
32<a href="../mod/mod_rewrite.html">reference documentation</a>. It provides
33a few advanced techniques using mod_rewrite.</p>
34
35<div class="warning">Note that many of these examples won't work unchanged in your
36particular server configuration, so it's important that you understand
37them, rather than merely cutting and pasting the examples into your
38configuration.</div>
39
40</div>
41<div id="quickview"><a href="https://www.apache.org/foundation/contributing.html" class="badge"><img src="https://www.apache.org/images/SupportApache-small.png" alt="Support Apache!" /></a><ul id="toc"><li><img alt="" src="../images/down.gif" /> <a href="#sharding">URL-based sharding across multiple backends</a></li>
42<li><img alt="" src="../images/down.gif" /> <a href="#on-the-fly-content">On-the-fly Content-Regeneration</a></li>
43<li><img alt="" src="../images/down.gif" /> <a href="#load-balancing">Load Balancing</a></li>
44<li><img alt="" src="../images/down.gif" /> <a href="#structuredhomedirs">Structured Userdirs</a></li>
45<li><img alt="" src="../images/down.gif" /> <a href="#redirectanchors">Redirecting Anchors</a></li>
46<li><img alt="" src="../images/down.gif" /> <a href="#time-dependent">Time-Dependent Rewriting</a></li>
47<li><img alt="" src="../images/down.gif" /> <a href="#setenvvars">Set Environment Variables Based On URL Parts</a></li>
48</ul><h3>See also</h3><ul class="seealso"><li><a href="../mod/mod_rewrite.html">Module documentation</a></li><li><a href="intro.html">mod_rewrite introduction</a></li><li><a href="remapping.html">Redirection and remapping</a></li><li><a href="access.html">Controlling access</a></li><li><a href="vhosts.html">Virtual hosts</a></li><li><a href="proxy.html">Proxying</a></li><li><a href="rewritemap.html">Using RewriteMap</a></li><li><a href="avoid.html">When not to use mod_rewrite</a></li><li><a href="#comments_section">Comments</a></li></ul></div>
49<div class="top"><a href="#page-header"><img alt="top" src="../images/up.gif" /></a></div>
50<div class="section">
51<h2><a name="sharding" id="sharding">URL-based sharding across multiple backends</a></h2>
52
53
54
55  <dl>
56    <dt>Description:</dt>
57
58    <dd>
59      <p>A common technique for distributing the burden of
60      server load or storage space is called "sharding".
61      When using this method, a front-end server will use the
62      url to consistently "shard" users or objects to separate
63      backend servers.</p>
64    </dd>
65
66    <dt>Solution:</dt>
67
68    <dd>
69      <p>A mapping is maintained, from users to target servers, in
70      external map files. They look like:</p>
71
72<div class="example"><p><code>
73user1  physical_host_of_user1<br />
74user2  physical_host_of_user2<br />
75# ... and so on
76</code></p></div>
77
78  <p>We put this into a <code>map.users-to-hosts</code> file. The
79    aim is to map;</p>
80
81<div class="example"><p><code>
82/u/user1/anypath
83</code></p></div>
84
85  <p>to</p>
86
87<div class="example"><p><code>
88http://physical_host_of_user1/u/user/anypath
89</code></p></div>
90
91      <p>thus every URL path need not be valid on every backend physical
92      host. The following ruleset does this for us with the help of the map
93      files assuming that server0 is a default server which will be used if
94      a user has no entry in the map:</p>
95
96<pre class="prettyprint lang-config">RewriteEngine on
97RewriteMap    users-to-hosts      "txt:/path/to/map.users-to-hosts"
98RewriteRule   "^/u/([^/]+)/?(.*)" "http://${users-to-hosts:$1|server0}/u/$1/$2"</pre>
99
100    </dd>
101  </dl>
102
103  <p>See the <code class="directive"><a href="../mod/mod_rewrite.html#rewritemap">RewriteMap</a></code>
104  documentation and the <a href="./rewritemap.html">RewriteMap HowTo</a>
105  for more discussion of the syntax of this directive.</p>
106
107</div><div class="top"><a href="#page-header"><img alt="top" src="../images/up.gif" /></a></div>
108<div class="section">
109<h2><a name="on-the-fly-content" id="on-the-fly-content">On-the-fly Content-Regeneration</a></h2>
110
111
112
113  <dl>
114    <dt>Description:</dt>
115
116    <dd>
117      <p>We wish to dynamically generate content, but store it
118      statically once it is generated. This rule will check for the
119      existence of the static file, and if it's not there, generate
120      it. The static files can be removed periodically, if desired (say,
121      via cron) and will be regenerated on demand.</p>
122    </dd>
123
124    <dt>Solution:</dt>
125
126    <dd>
127      This is done via the following ruleset:
128
129<pre class="prettyprint lang-config"># This example is valid in per-directory context only
130RewriteCond "%{REQUEST_URI}"   "!-U"
131RewriteRule "^(.+)\.html$"     "/regenerate_page.cgi"   [PT,L]</pre>
132
133
134    <p>The <code>-U</code> operator determines whether the test string
135    (in this case, <code>REQUEST_URI</code>) is a valid URL. It does
136    this via a subrequest. In the event that this subrequest fails -
137    that is, the requested resource doesn't exist - this rule invokes
138    the CGI program <code>/regenerate_page.cgi</code>, which generates
139    the requested resource and saves it into the document directory, so
140    that the next time it is requested, a static copy can be served.</p>
141
142    <p>In this way, documents that are infrequently updated can be served in
143    static form. if documents need to be refreshed, they can be deleted
144    from the document directory, and they will then be regenerated the
145    next time they are requested.</p>
146    </dd>
147  </dl>
148
149</div><div class="top"><a href="#page-header"><img alt="top" src="../images/up.gif" /></a></div>
150<div class="section">
151<h2><a name="load-balancing" id="load-balancing">Load Balancing</a></h2>
152
153
154
155  <dl>
156    <dt>Description:</dt>
157
158    <dd>
159      <p>We wish to randomly distribute load across several servers
160      using mod_rewrite.</p>
161    </dd>
162
163    <dt>Solution:</dt>
164
165    <dd>
166      <p>We'll use <code class="directive"><a href="../mod/mod_rewrite.html#rewritemap">RewriteMap</a></code> and a list of servers
167      to accomplish this.</p>
168
169<pre class="prettyprint lang-config">RewriteEngine on
170RewriteMap lb        "rnd:/path/to/serverlist.txt"
171RewriteRule "^/(.*)" "http://${lb:servers}/$1"     [P,L]</pre>
172
173
174<p><code>serverlist.txt</code> will contain a list of the servers:</p>
175
176<div class="example"><p><code>
177## serverlist.txt<br />
178<br />
179servers one.example.com|two.example.com|three.example.com<br />
180</code></p></div>
181
182<p>If you want one particular server to get more of the load than the
183others, add it more times to the list.</p>
184
185   </dd>
186
187   <dt>Discussion</dt>
188   <dd>
189<p>Apache comes with a load-balancing module -
190<code class="module"><a href="../mod/mod_proxy_balancer.html">mod_proxy_balancer</a></code> - which is far more flexible and
191featureful than anything you can cobble together using mod_rewrite.</p>
192   </dd>
193  </dl>
194
195</div><div class="top"><a href="#page-header"><img alt="top" src="../images/up.gif" /></a></div>
196<div class="section">
197<h2><a name="structuredhomedirs" id="structuredhomedirs">Structured Userdirs</a></h2>
198
199
200
201  <dl>
202    <dt>Description:</dt>
203
204    <dd>
205      <p>Some sites with thousands of users use a
206      structured homedir layout, <em>i.e.</em> each homedir is in a
207      subdirectory which begins (for instance) with the first
208      character of the username. So, <code>/~larry/anypath</code>
209      is <code>/home/<strong>l</strong>/larry/public_html/anypath</code>
210      while <code>/~waldo/anypath</code> is
211      <code>/home/<strong>w</strong>/waldo/public_html/anypath</code>.</p>
212    </dd>
213
214    <dt>Solution:</dt>
215
216    <dd>
217      <p>We use the following ruleset to expand the tilde URLs
218      into the above layout.</p>
219
220<pre class="prettyprint lang-config">RewriteEngine on
221RewriteRule   "^/~(<strong>([a-z])</strong>[a-z0-9]+)(.*)"  "/home/<strong>$2</strong>/$1/public_html$3"</pre>
222
223    </dd>
224  </dl>
225
226</div><div class="top"><a href="#page-header"><img alt="top" src="../images/up.gif" /></a></div>
227<div class="section">
228<h2><a name="redirectanchors" id="redirectanchors">Redirecting Anchors</a></h2>
229
230
231
232  <dl>
233    <dt>Description:</dt>
234
235    <dd>
236    <p>By default, redirecting to an HTML anchor doesn't work,
237    because mod_rewrite escapes the <code>#</code> character,
238    turning it into <code>%23</code>. This, in turn, breaks the
239    redirection.</p>
240    </dd>
241
242    <dt>Solution:</dt>
243
244    <dd>
245      <p>Use the <code>[NE]</code> flag on the
246      <code>RewriteRule</code>. NE stands for No Escape.
247      </p>
248    </dd>
249
250    <dt>Discussion:</dt>
251    <dd>This technique will of course also work with other
252    special characters that mod_rewrite, by default, URL-encodes.</dd>
253  </dl>
254
255</div><div class="top"><a href="#page-header"><img alt="top" src="../images/up.gif" /></a></div>
256<div class="section">
257<h2><a name="time-dependent" id="time-dependent">Time-Dependent Rewriting</a></h2>
258
259
260
261  <dl>
262    <dt>Description:</dt>
263
264    <dd>
265      <p>We wish to use mod_rewrite to serve different content based on
266      the time of day.</p>
267    </dd>
268
269    <dt>Solution:</dt>
270
271    <dd>
272      <p>There are a lot of variables named <code>TIME_xxx</code>
273      for rewrite conditions. In conjunction with the special
274      lexicographic comparison patterns <code>&lt;STRING</code>,
275      <code>&gt;STRING</code> and <code>=STRING</code> we can
276      do time-dependent redirects:</p>
277
278<pre class="prettyprint lang-config">RewriteEngine on
279RewriteCond   "%{TIME_HOUR}%{TIME_MIN}" "&gt;0700"
280RewriteCond   "%{TIME_HOUR}%{TIME_MIN}" "&lt;1900"
281RewriteRule   "^foo\.html$"             "foo.day.html" [L]
282RewriteRule   "^foo\.html$"             "foo.night.html"</pre>
283
284
285      <p>This provides the content of <code>foo.day.html</code>
286      under the URL <code>foo.html</code> from
287      <code>07:01-18:59</code> and at the remaining time the
288      contents of <code>foo.night.html</code>.</p>
289
290      <div class="warning"><code class="module"><a href="../mod/mod_cache.html">mod_cache</a></code>, intermediate proxies
291      and browsers may each cache responses and cause the either page to be
292      shown outside of the time-window configured.
293      <code class="module"><a href="../mod/mod_expires.html">mod_expires</a></code> may be used to control this
294      effect. You are, of course, much better off simply serving the
295      content dynamically, and customizing it based on the time of day.</div>
296
297    </dd>
298  </dl>
299
300</div><div class="top"><a href="#page-header"><img alt="top" src="../images/up.gif" /></a></div>
301<div class="section">
302<h2><a name="setenvvars" id="setenvvars">Set Environment Variables Based On URL Parts</a></h2>
303
304
305
306  <dl>
307    <dt>Description:</dt>
308
309    <dd>
310      <p>At times, we want to maintain some kind of status when we
311      perform a rewrite. For example, you want to make a note that
312      you've done that rewrite, so that you can check later to see if a
313      request came via that rewrite. One way to do this is by setting an
314      environment variable.</p>
315    </dd>
316
317    <dt>Solution:</dt>
318
319    <dd>
320      <p>Use the [E] flag to set an environment variable.</p>
321
322<pre class="prettyprint lang-config">RewriteEngine on
323RewriteRule   "^/horse/(.*)"   "/pony/$1" [E=<strong>rewritten:1</strong>]</pre>
324
325
326    <p>Later in your ruleset you might check for this environment
327    variable using a RewriteCond:</p>
328
329<pre class="prettyprint lang-config">RewriteCond "%{ENV:rewritten}" "=1"</pre>
330
331
332    <p>Note that environment variables do not survive an external
333    redirect. You might consider using the [CO] flag to set a
334    cookie. For per-directory and htaccess rewrites, where the final
335    substitution is processed as an internal redirect, environment
336    variables from the previous round of rewriting are prefixed with
337    "REDIRECT_". </p>
338
339    </dd>
340  </dl>
341
342</div></div>
343<div class="bottomlang">
344<p><span>Available Languages: </span><a href="../en/rewrite/advanced.html" title="English">&nbsp;en&nbsp;</a> |
345<a href="../fr/rewrite/advanced.html" hreflang="fr" rel="alternate" title="Français">&nbsp;fr&nbsp;</a></p>
346</div><div class="top"><a href="#page-header"><img src="../images/up.gif" alt="top" /></a></div><div class="section"><h2><a id="comments_section" name="comments_section">Comments</a></h2><div class="warning"><strong>Notice:</strong><br />This is not a Q&amp;A section. Comments placed here should be pointed towards suggestions on improving the documentation or server, and may be removed 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 Libera.chat, or sent to our <a href="https://httpd.apache.org/lists.html">mailing lists</a>.</div>
347<script type="text/javascript"><!--//--><![CDATA[//><!--
348var comments_shortname = 'httpd';
349var comments_identifier = 'http://httpd.apache.org/docs/2.4/rewrite/advanced.html';
350(function(w, d) {
351    if (w.location.hostname.toLowerCase() == "httpd.apache.org") {
352        d.write('<div id="comments_thread"><\/div>');
353        var s = d.createElement('script');
354        s.type = 'text/javascript';
355        s.async = true;
356        s.src = 'https://comments.apache.org/show_comments.lua?site=' + comments_shortname + '&page=' + comments_identifier;
357        (d.getElementsByTagName('head')[0] || d.getElementsByTagName('body')[0]).appendChild(s);
358    }
359    else {
360        d.write('<div id="comments_thread">Comments are disabled for this page at the moment.<\/div>');
361    }
362})(window, document);
363//--><!]]></script></div><div id="footer">
364<p class="apache">Copyright 2022 The Apache Software Foundation.<br />Licensed under the <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache License, Version 2.0</a>.</p>
365<p class="menu"><a href="../mod/">Modules</a> | <a href="../mod/directives.html">Directives</a> | <a href="http://wiki.apache.org/httpd/FAQ">FAQ</a> | <a href="../glossary.html">Glossary</a> | <a href="../sitemap.html">Sitemap</a></p></div><script type="text/javascript"><!--//--><![CDATA[//><!--
366if (typeof(prettyPrint) !== 'undefined') {
367    prettyPrint();
368}
369//--><!]]></script>
370</body></html>