]> granicus.if.org Git - apache/blob - docs/manual/rewrite/advanced.html.en
Rebuilding with new CSS/JS syntax highlighting stuff turned on.
[apache] / docs / manual / rewrite / advanced.html.en
1 <?xml version="1.0" encoding="ISO-8859-1"?>
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         XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
5               This file is generated from xml source: DO NOT EDIT
6         XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
7       -->
8 <title>Advanced Techniques with mod_rewrite - Apache HTTP Server</title>
9 <link href="../style/css/manual.css" rel="stylesheet" media="all" type="text/css" title="Main stylesheet" />
10 <link href="../style/css/manual-loose-100pc.css" rel="alternate stylesheet" media="all" type="text/css" title="No Sidebar - Default font size" />
11 <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" />
12 <script src="../style/scripts/prettify.js" type="text/javascript">
13 </script>
14
15 <link href="../images/favicon.ico" rel="shortcut icon" /></head>
16 <body id="manual-page"><div id="page-header">
17 <p class="menu"><a href="../mod/">Modules</a> | <a href="../mod/directives.html">Directives</a> | <a href="../faq/">FAQ</a> | <a href="../glossary.html">Glossary</a> | <a href="../sitemap.html">Sitemap</a></p>
18 <p class="apache">Apache HTTP Server Version 2.5</p>
19 <img alt="" src="../images/feather.gif" /></div>
20 <div class="up"><a href="./"><img title="&lt;-" alt="&lt;-" src="../images/left.gif" /></a></div>
21 <div id="path">
22 <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.5</a> &gt; <a href="./">Rewrite</a></div><div id="page-content"><div id="preamble"><h1>Advanced Techniques with mod_rewrite</h1>
23 <div class="toplang">
24 <p><span>Available Languages: </span><a href="../en/rewrite/avoid.html" title="English">&nbsp;en&nbsp;</a></p>
25 </div>
26
27
28 <p>This document supplements the <code class="module"><a href="../mod/mod_rewrite.html">mod_rewrite</a></code>
29 <a href="../mod/mod_rewrite.html">reference documentation</a>. It provides
30 a few advanced techniques using mod_rewrite.</p>
31
32 <div class="warning">Note that many of these examples won't work unchanged in your
33 particular server configuration, so it's important that you understand
34 them, rather than merely cutting and pasting the examples into your
35 configuration.</div>
36
37 </div>
38 <div id="quickview"><ul id="toc"><li><img alt="" src="../images/down.gif" /> <a href="#sharding">URL-based sharding accross multiple backends</a></li>
39 <li><img alt="" src="../images/down.gif" /> <a href="#on-the-fly-content">On-the-fly Content-Regeneration</a></li>
40 <li><img alt="" src="../images/down.gif" /> <a href="#load-balancing">Load Balancing</a></li>
41 <li><img alt="" src="../images/down.gif" /> <a href="#autorefresh">Document With Autorefresh</a></li>
42 <li><img alt="" src="../images/down.gif" /> <a href="#structuredhomedirs">Structured Userdirs</a></li>
43 <li><img alt="" src="../images/down.gif" /> <a href="#redirectanchors">Redirecting Anchors</a></li>
44 <li><img alt="" src="../images/down.gif" /> <a href="#time-dependent">Time-Dependent Rewriting</a></li>
45 <li><img alt="" src="../images/down.gif" /> <a href="#setenvvars">Set Environment Variables Based On URL Parts</a></li>
46 </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></ul></div>
47 <div class="top"><a href="#page-header"><img alt="top" src="../images/up.gif" /></a></div>
48 <div class="section">
49 <h2><a name="sharding" id="sharding">URL-based sharding accross multiple backends</a></h2>
50
51   
52
53   <dl>
54     <dt>Description:</dt>
55
56     <dd>
57       <p>A common technique for distributing the burden of
58       server load or storage space is called "sharding".
59       When using this method, a front-end server will use the
60       url to consistently "shard" users or objects to separate
61       backend servers.</p>
62     </dd>
63
64     <dt>Solution:</dt>
65
66     <dd>
67       <p>A mapping is maintained, from users to target servers, in
68       external map files. They look like:</p>
69
70 <div class="example"><p><code>
71 user1  physical_host_of_user1<br />
72 user2  physical_host_of_user2<br />
73 :      :
74 </code></p></div>
75
76   <p>We put this into a <code>map.users-to-hosts</code> file. The
77     aim is to map;</p>
78
79 <div class="example"><p><code>
80 /u/user1/anypath
81 </code></p></div>
82
83   <p>to</p>
84
85 <div class="example"><p><code>
86 http://physical_host_of_user1/u/user/anypath
87 </code></p></div>
88
89       <p>thus every URL path need not be valid on every backend physical
90       host. The following ruleset does this for us with the help of the map
91       files assuming that server0 is a default server which will be used if
92       a user has no entry in the map:</p>
93
94 <div class="example"><p><code>
95 RewriteEngine on<br />
96 <br />
97 RewriteMap      users-to-hosts   txt:/path/to/map.users-to-hosts<br />
98 <br />
99 RewriteRule   ^/u/<strong>([^/]+)</strong>/?(.*)   http://<strong>${users-to-hosts:$1|server0}</strong>/u/$1/$2
100 </code></p></div>
101     </dd>
102   </dl>
103
104   <p>See the <code class="directive"><a href="../mod/mod_rewrite.html#rewritemap">RewriteMap</a></code>
105   documentation 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 <div class="example"><p><code>
130 # This example is valid in per-directory context only<br />
131 RewriteCond %{REQUEST_URI}   <strong>!-U</strong><br />
132 RewriteRule ^(.+)\.html$          /regenerate_page.cgi   [PT,L]
133 </code></p></div>
134
135     <p>The <code>-U</code> operator determines whether the test string
136     (in this case, <code>REQUEST_URI</code>) is a valid URL. It does
137     this via a subrequest. In the event that this subrequest fails -
138     that is, the requested resource doesn't exist - this rule invokes
139     the CGI program <code>/regenerate_page.cgi</code>, which generates
140     the requested resource and saves it into the document directory, so
141     that the next time it is requested, a static copy can be served.</p>
142
143     <p>In this way, documents that are infrequently updated can be served in
144     static form. if documents need to be refreshed, they can be deleted
145     from the document directory, and they will then be regenerated the
146     next time they are requested.</p>
147     </dd>
148   </dl>
149
150 </div><div class="top"><a href="#page-header"><img alt="top" src="../images/up.gif" /></a></div>
151 <div class="section">
152 <h2><a name="load-balancing" id="load-balancing">Load Balancing</a></h2>
153
154   
155
156   <dl>
157     <dt>Description:</dt>
158
159     <dd>
160       <p>We wish to randomly distribute load across several servers
161       using mod_rewrite.</p>
162     </dd>
163
164     <dt>Solution:</dt>
165
166     <dd>
167       <p>We'll use <code class="directive"><a href="../mod/mod_rewrite.html#rewritemap">RewriteMap</a></code> and a list of servers
168       to accomplish this.</p>
169
170 <div class="example"><p><code>
171 RewriteEngine on<br />
172 RewriteMap lb rnd:/path/to/serverlist.txt<br />
173 <br />
174 RewriteRule ^/(.*) http://${lb:servers}/$1 [P,L]
175 </code></p></div>
176
177 <p><code>serverlist.txt</code> will contain a list of the servers:</p>
178
179 <div class="example"><p><code>
180 ## serverlist.txt<br />
181 <br />
182 servers one.example.com|two.example.com|three.example.com<br />
183 </code></p></div>
184
185 <p>If you want one particular server to get more of the load than the
186 others, add it more times to the list.</p>
187
188    </dd>
189
190    <dt>Discussion</dt>
191    <dd>
192 <p>Apache comes with a load-balancing module -
193 <code class="module"><a href="../mod/mod_proxy_balancer.html">mod_proxy_balancer</a></code> - which is far more flexible and
194 featureful than anything you can cobble together using mod_rewrite.</p>
195    </dd>
196   </dl>
197
198 </div><div class="top"><a href="#page-header"><img alt="top" src="../images/up.gif" /></a></div>
199 <div class="section">
200 <h2><a name="autorefresh" id="autorefresh">Document With Autorefresh</a></h2>
201
202   
203
204
205
206   <dl>
207     <dt>Description:</dt>
208
209     <dd>
210       <p>Wouldn't it be nice, while creating a complex web page, if
211       the web browser would automatically refresh the page every
212       time we save a new version from within our editor?
213       Impossible?</p>
214     </dd>
215
216     <dt>Solution:</dt>
217
218     <dd>
219       <p>No! We just combine the MIME multipart feature, the
220       web server NPH feature, and the URL manipulation power of
221       <code class="module"><a href="../mod/mod_rewrite.html">mod_rewrite</a></code>. First, we establish a new
222       URL feature: Adding just <code>:refresh</code> to any
223       URL causes the 'page' to be refreshed every time it is
224       updated on the filesystem.</p>
225
226 <div class="example"><p><code>
227 RewriteRule   ^(/[uge]/[^/]+/?.*):refresh  /internal/cgi/apache/nph-refresh?f=$1
228 </code></p></div>
229
230       <p>Now when we reference the URL</p>
231
232 <div class="example"><p><code>
233 /u/foo/bar/page.html:refresh
234 </code></p></div>
235
236       <p>this leads to the internal invocation of the URL</p>
237
238 <div class="example"><p><code>
239 /internal/cgi/apache/nph-refresh?f=/u/foo/bar/page.html
240 </code></p></div>
241
242       <p>The only missing part is the NPH-CGI script. Although
243       one would usually say "left as an exercise to the reader"
244       ;-) I will provide this, too.</p>
245
246 <div class="example"><pre>
247 #!/sw/bin/perl
248 ##
249 ##  nph-refresh -- NPH/CGI script for auto refreshing pages
250 ##  Copyright (c) 1997 Ralf S. Engelschall, All Rights Reserved.
251 ##
252 $| = 1;
253
254 #   split the QUERY_STRING variable
255 @pairs = split(/&amp;/, $ENV{'QUERY_STRING'});
256 foreach $pair (@pairs) {
257 ($name, $value) = split(/=/, $pair);
258 $name =~ tr/A-Z/a-z/;
259 $name = 'QS_' . $name;
260 $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
261 eval "\$$name = \"$value\"";
262 }
263 $QS_s = 1 if ($QS_s eq '');
264 $QS_n = 3600 if ($QS_n eq '');
265 if ($QS_f eq '') {
266 print "HTTP/1.0 200 OK\n";
267 print "Content-type: text/html\n\n";
268 print "&amp;lt;b&amp;gt;ERROR&amp;lt;/b&amp;gt;: No file given\n";
269 exit(0);
270 }
271 if (! -f $QS_f) {
272 print "HTTP/1.0 200 OK\n";
273 print "Content-type: text/html\n\n";
274 print "&amp;lt;b&amp;gt;ERROR&amp;lt;/b&amp;gt;: File $QS_f not found\n";
275 exit(0);
276 }
277
278 sub print_http_headers_multipart_begin {
279 print "HTTP/1.0 200 OK\n";
280 $bound = "ThisRandomString12345";
281 print "Content-type: multipart/x-mixed-replace;boundary=$bound\n";
282 &amp;print_http_headers_multipart_next;
283 }
284
285 sub print_http_headers_multipart_next {
286 print "\n--$bound\n";
287 }
288
289 sub print_http_headers_multipart_end {
290 print "\n--$bound--\n";
291 }
292
293 sub displayhtml {
294 local($buffer) = @_;
295 $len = length($buffer);
296 print "Content-type: text/html\n";
297 print "Content-length: $len\n\n";
298 print $buffer;
299 }
300
301 sub readfile {
302 local($file) = @_;
303 local(*FP, $size, $buffer, $bytes);
304 ($x, $x, $x, $x, $x, $x, $x, $size) = stat($file);
305 $size = sprintf("%d", $size);
306 open(FP, "&amp;lt;$file");
307 $bytes = sysread(FP, $buffer, $size);
308 close(FP);
309 return $buffer;
310 }
311
312 $buffer = &amp;readfile($QS_f);
313 &amp;print_http_headers_multipart_begin;
314 &amp;displayhtml($buffer);
315
316 sub mystat {
317 local($file) = $_[0];
318 local($time);
319
320 ($x, $x, $x, $x, $x, $x, $x, $x, $x, $mtime) = stat($file);
321 return $mtime;
322 }
323
324 $mtimeL = &amp;mystat($QS_f);
325 $mtime = $mtime;
326 for ($n = 0; $n &amp;lt; $QS_n; $n++) {
327 while (1) {
328     $mtime = &amp;mystat($QS_f);
329     if ($mtime ne $mtimeL) {
330         $mtimeL = $mtime;
331         sleep(2);
332         $buffer = &amp;readfile($QS_f);
333         &amp;print_http_headers_multipart_next;
334         &amp;displayhtml($buffer);
335         sleep(5);
336         $mtimeL = &amp;mystat($QS_f);
337         last;
338     }
339     sleep($QS_s);
340 }
341 }
342
343 &amp;print_http_headers_multipart_end;
344
345 exit(0);
346
347 ##EOF##
348 </pre></div>
349     </dd>
350   </dl>
351
352 </div><div class="top"><a href="#page-header"><img alt="top" src="../images/up.gif" /></a></div>
353 <div class="section">
354 <h2><a name="structuredhomedirs" id="structuredhomedirs">Structured Userdirs</a></h2>
355
356   
357
358   <dl>
359     <dt>Description:</dt>
360
361     <dd>
362       <p>Some sites with thousands of users use a
363       structured homedir layout, <em>i.e.</em> each homedir is in a
364       subdirectory which begins (for instance) with the first
365       character of the username. So, <code>/~larry/anypath</code>
366       is <code>/home/<strong>l</strong>/larry/public_html/anypath</code>
367       while <code>/~waldo/anypath</code> is
368       <code>/home/<strong>w</strong>/waldo/public_html/anypath</code>.</p>
369     </dd>
370
371     <dt>Solution:</dt>
372
373     <dd>
374       <p>We use the following ruleset to expand the tilde URLs
375       into the above layout.</p>
376
377 <div class="example"><p><code>
378 RewriteEngine on<br />
379 RewriteRule   ^/~(<strong>([a-z])</strong>[a-z0-9]+)(.*)  /home/<strong>$2</strong>/$1/public_html$3
380 </code></p></div>
381     </dd>
382   </dl>
383
384 </div><div class="top"><a href="#page-header"><img alt="top" src="../images/up.gif" /></a></div>
385 <div class="section">
386 <h2><a name="redirectanchors" id="redirectanchors">Redirecting Anchors</a></h2>
387
388   
389
390   <dl>
391     <dt>Description:</dt>
392
393     <dd>
394     <p>By default, redirecting to an HTML anchor doesn't work,
395     because mod_rewrite escapes the <code>#</code> character,
396     turning it into <code>%23</code>. This, in turn, breaks the
397     redirection.</p>
398     </dd>
399
400     <dt>Solution:</dt>
401
402     <dd>
403       <p>Use the <code>[NE]</code> flag on the
404       <code>RewriteRule</code>. NE stands for No Escape.
405       </p>
406     </dd>
407
408     <dt>Discussion:</dt>
409     <dd>This technique will of course also work with other
410     special characters that mod_rewrite, by default, URL-encodes.</dd>
411   </dl>
412
413 </div><div class="top"><a href="#page-header"><img alt="top" src="../images/up.gif" /></a></div>
414 <div class="section">
415 <h2><a name="time-dependent" id="time-dependent">Time-Dependent Rewriting</a></h2>
416
417   
418
419   <dl>
420     <dt>Description:</dt>
421
422     <dd>
423       <p>We wish to use mod_rewrite to serve different content based on
424       the time of day.</p>
425     </dd>
426
427     <dt>Solution:</dt>
428
429     <dd>
430       <p>There are a lot of variables named <code>TIME_xxx</code>
431       for rewrite conditions. In conjunction with the special
432       lexicographic comparison patterns <code>&lt;STRING</code>,
433       <code>&gt;STRING</code> and <code>=STRING</code> we can
434       do time-dependent redirects:</p>
435
436 <div class="example"><p><code>
437 RewriteEngine on<br />
438 RewriteCond   %{TIME_HOUR}%{TIME_MIN} &gt;0700<br />
439 RewriteCond   %{TIME_HOUR}%{TIME_MIN} &lt;1900<br />
440 RewriteRule   ^foo\.html$             foo.day.html [L]<br />
441 RewriteRule   ^foo\.html$             foo.night.html
442 </code></p></div>
443
444       <p>This provides the content of <code>foo.day.html</code>
445       under the URL <code>foo.html</code> from
446       <code>07:01-18:59</code> and at the remaining time the
447       contents of <code>foo.night.html</code>.</p>
448
449       <div class="warning"><code class="module"><a href="../mod/mod_cache.html">mod_cache</a></code>, intermediate proxies
450       and browsers may each cache responses and cause the either page to be
451       shown outside of the time-window configured.
452       <code class="module"><a href="../mod/mod_expires.html">mod_expires</a></code> may be used to control this
453       effect. You are, of course, much better off simply serving the
454       content dynamically, and customizing it based on the time of day.</div>
455
456     </dd>
457   </dl>
458
459 </div><div class="top"><a href="#page-header"><img alt="top" src="../images/up.gif" /></a></div>
460 <div class="section">
461 <h2><a name="setenvvars" id="setenvvars">Set Environment Variables Based On URL Parts</a></h2>
462
463   
464
465   <dl>
466     <dt>Description:</dt>
467
468     <dd>
469       <p>At time, we want to maintain some kind of status when we
470       perform a rewrite. For example, you want to make a note that
471       you've done that rewrite, so that you can check later to see if a
472       request can via that rewrite. One way to do this is by setting an
473       environment variable.</p>
474     </dd>
475
476     <dt>Solution:</dt>
477
478     <dd>
479       <p>Use the [E] flag to set an environment variable.</p>
480
481 <div class="example"><p><code>
482 RewriteEngine on<br />
483 RewriteRule   ^/horse/(.*)   /pony/$1 [E=<strong>rewritten:1</strong>]
484 </code></p></div>
485
486     <p>Later in your ruleset you might check for this environment
487     variable using a RewriteCond:</p>
488
489 <div class="example"><p><code>
490 RewriteCond %{ENV:rewritten} =1
491 </code></p></div>
492
493     <p>Note that environment variables do not survive an external
494     redirect. You might consider using the [CO] flag to set a
495     cookie.</p>
496
497     </dd>
498   </dl>
499
500 </div></div>
501 <div class="bottomlang">
502 <p><span>Available Languages: </span><a href="../en/rewrite/avoid.html" title="English">&nbsp;en&nbsp;</a></p>
503 </div><div id="footer">
504 <p class="apache">Copyright 2012 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>
505 <p class="menu"><a href="../mod/">Modules</a> | <a href="../mod/directives.html">Directives</a> | <a href="../faq/">FAQ</a> | <a href="../glossary.html">Glossary</a> | <a href="../sitemap.html">Sitemap</a></p></div><script type="text/javascript">
506     if (prettyPrint) {
507         prettyPrint();
508     }
509 </script>
510 </body></html>