upload http
[bottlenecks.git] / rubbos / app / httpd-2.0.64 / docs / manual / misc / rewriteguide.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>URL Rewriting Guide - 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" />
12 <link href="../images/favicon.ico" rel="shortcut icon" /></head>
13 <body id="manual-page"><div id="page-header">
14 <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>
15 <p class="apache">Apache HTTP Server Version 2.0</p>
16 <img alt="" src="../images/feather.gif" /></div>
17 <div class="up"><a href="./"><img title="&lt;-" alt="&lt;-" src="../images/left.gif" /></a></div>
18 <div id="path">
19 <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.0</a> &gt; <a href="./">Miscellaneous Documentation</a></div><div id="page-content"><div id="preamble"><h1>URL Rewriting Guide</h1>
20 <div class="toplang">
21 <p><span>Available Languages: </span><a href="../en/misc/rewriteguide.html" title="English">&nbsp;en&nbsp;</a> |
22 <a href="../ko/misc/rewriteguide.html" hreflang="ko" rel="alternate" title="Korean">&nbsp;ko&nbsp;</a></p>
23 </div>
24
25     <div class="note">
26       <p>Originally written by<br />
27       <cite>Ralf S. Engelschall &lt;rse@apache.org&gt;</cite><br />
28       December 1997</p>
29     </div>
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>.
33     It describes how one can use Apache's <code class="module"><a href="../mod/mod_rewrite.html">mod_rewrite</a></code>
34     to solve typical URL-based problems with which webmasters are
35     commonony confronted. We give detailed descriptions on how to
36     solve each problem by configuring URL rewriting rulesets.</p>
37
38   </div>
39 <div id="quickview"><ul id="toc"><li><img alt="" src="../images/down.gif" /> <a href="#ToC1">Introduction to <code>mod_rewrite</code></a></li>
40 <li><img alt="" src="../images/down.gif" /> <a href="#ToC2">Practical Solutions</a></li>
41 <li><img alt="" src="../images/down.gif" /> <a href="#url">URL Layout</a></li>
42 <li><img alt="" src="../images/down.gif" /> <a href="#content">Content Handling</a></li>
43 <li><img alt="" src="../images/down.gif" /> <a href="#access">Access Restriction</a></li>
44 <li><img alt="" src="../images/down.gif" /> <a href="#other">Other</a></li>
45 </ul></div>
46 <div class="top"><a href="#page-header"><img alt="top" src="../images/up.gif" /></a></div>
47 <div class="section">
48 <h2><a name="ToC1" id="ToC1">Introduction to <code>mod_rewrite</code></a></h2>
49
50     
51
52     <p>The Apache module <code class="module"><a href="../mod/mod_rewrite.html">mod_rewrite</a></code> is a killer
53     one, i.e. it is a really sophisticated module which provides
54     a powerful way to do URL manipulations. With it you can do nearly 
55     all types of URL manipulations you ever dreamed about.
56     The price you have to pay is to accept complexity, because
57     <code class="module"><a href="../mod/mod_rewrite.html">mod_rewrite</a></code>'s major drawback is that it is
58     not easy to understand and use for the beginner. And even
59     Apache experts sometimes discover new aspects where
60     <code class="module"><a href="../mod/mod_rewrite.html">mod_rewrite</a></code> can help.</p>
61
62     <p>In other words: With <code class="module"><a href="../mod/mod_rewrite.html">mod_rewrite</a></code> you either
63     shoot yourself in the foot the first time and never use it again
64     or love it for the rest of your life because of its power.
65     This paper tries to give you a few initial success events to
66     avoid the first case by presenting already invented solutions
67     to you.</p>
68
69   </div><div class="top"><a href="#page-header"><img alt="top" src="../images/up.gif" /></a></div>
70 <div class="section">
71 <h2><a name="ToC2" id="ToC2">Practical Solutions</a></h2>
72
73     
74
75     <p>Here come a lot of practical solutions I've either invented
76     myself or collected from other people's solutions in the past.
77     Feel free to learn the black magic of URL rewriting from
78     these examples.</p>
79
80     <div class="warning">ATTENTION: Depending on your server-configuration
81     it can be necessary to slightly change the examples for your
82     situation, e.g. adding the <code>[PT]</code> flag when
83     additionally using <code class="module"><a href="../mod/mod_alias.html">mod_alias</a></code> and
84     <code class="module"><a href="../mod/mod_userdir.html">mod_userdir</a></code>, etc. Or rewriting a ruleset
85     to fit in <code>.htaccess</code> context instead
86     of per-server context. Always try to understand what a
87     particular ruleset really does before you use it. It
88     avoid problems.</div>
89
90   </div><div class="top"><a href="#page-header"><img alt="top" src="../images/up.gif" /></a></div>
91 <div class="section">
92 <h2><a name="url" id="url">URL Layout</a></h2>
93
94     
95
96     <h3>Canonical URLs</h3>
97
98       
99
100       <dl>
101         <dt>Description:</dt>
102
103         <dd>
104           <p>On some webservers there are more than one URL for a
105           resource. Usually there are canonical URLs (which should be
106           actually used and distributed) and those which are just
107           shortcuts, internal ones, etc. Independent of which URL the
108           user supplied with the request he should finally see the
109           canonical one only.</p>
110         </dd>
111
112         <dt>Solution:</dt>
113
114         <dd>
115           <p>We do an external HTTP redirect for all non-canonical
116           URLs to fix them in the location view of the Browser and
117           for all subsequent requests. In the example ruleset below
118           we replace <code>/~user</code> by the canonical
119           <code>/u/user</code> and fix a missing trailing slash for
120           <code>/u/user</code>.</p>
121
122 <div class="example"><pre>
123 RewriteRule   ^/<strong>~</strong>([^/]+)/?(.*)    /<strong>u</strong>/$1/$2  [<strong>R</strong>]
124 RewriteRule   ^/([uge])/(<strong>[^/]+</strong>)$  /$1/$2<strong>/</strong>   [<strong>R</strong>]
125 </pre></div>
126         </dd>
127       </dl>
128
129     
130
131     <h3>Canonical Hostnames</h3>
132
133       
134
135       <dl>
136         <dt>Description:</dt>
137
138         <dd>The goal of this rule is to force the use of a particular
139         hostname, in preference to other hostnames which may be used to
140         reach the same site. For example, if you wish to force the use
141         of <strong>www.example.com</strong> instead of
142         <strong>example.com</strong>, you might use a variant of the
143         following recipe.</dd>
144
145         <dt>Solution:</dt>
146
147         <dd>
148 <div class="example"><pre>
149 # For sites running on a port other than 80
150 RewriteCond %{HTTP_HOST}   !^www\.example\.com [NC]
151 RewriteCond %{HTTP_HOST}   !^$
152 RewriteCond %{SERVER_PORT} !^80$
153 RewriteRule ^/(.*)         http://www.example.com:%{SERVER_PORT}/$1 [L,R]
154
155 # And for a site running on port 80
156 RewriteCond %{HTTP_HOST}   !^www\.example\.com [NC]
157 RewriteCond %{HTTP_HOST}   !^$
158 RewriteRule ^/(.*)         http://www.example.com/$1 [L,R]
159 </pre></div>
160         </dd>
161       </dl>
162
163     
164
165     <h3>Moved <code>DocumentRoot</code></h3>
166
167       
168
169       <dl>
170         <dt>Description:</dt>
171
172         <dd>
173           <p>Usually the <code class="directive"><a href="../mod/core.html#documentroot">DocumentRoot</a></code>
174           of the webserver directly relates to the URL "<code>/</code>".
175           But often this data is not really of top-level priority, it is
176           perhaps just one entity of a lot of data pools. For instance at
177           our Intranet sites there are <code>/e/www/</code>
178           (the homepage for WWW), <code>/e/sww/</code> (the homepage for
179           the Intranet) etc. Now because the data of the <code class="directive"><a href="../mod/core.html#documentroot">DocumentRoot</a></code> stays at <code>/e/www/</code> we had
180           to make sure that all inlined images and other stuff inside this
181           data pool work for subsequent requests.</p>
182         </dd>
183
184         <dt>Solution:</dt>
185
186         <dd>
187           <p>We redirect the URL <code>/</code> to
188           <code>/e/www/</code>:
189           </p>
190          
191 <div class="example"><pre>
192 RewriteEngine on
193 RewriteRule   <strong>^/$</strong>  /e/www/  [<strong>R</strong>]
194 </pre></div>
195
196     <p>Note that this can also be handled using the <code class="directive"><a href="../mod/mod_alias.html#redirectmatch">RedirectMatch</a></code> directive:</p>
197
198     <div class="example"><p><code>
199     RedirectMatch ^/$ http://example.com/e/www/
200     </code></p></div>
201         </dd>
202       </dl>
203
204     
205
206     <h3>Trailing Slash Problem</h3>
207
208       
209
210       <dl>
211         <dt>Description:</dt>
212
213         <dd>
214           <p>Every webmaster can sing a song about the problem of
215           the trailing slash on URLs referencing directories. If they
216           are missing, the server dumps an error, because if you say
217           <code>/~quux/foo</code> instead of <code>/~quux/foo/</code>
218           then the server searches for a <em>file</em> named
219           <code>foo</code>. And because this file is a directory it
220           complains. Actually it tries to fix it itself in most of
221           the cases, but sometimes this mechanism need to be emulated
222           by you. For instance after you have done a lot of
223           complicated URL rewritings to CGI scripts etc.</p>
224         </dd>
225
226         <dt>Solution:</dt>
227
228         <dd>
229           <p>The solution to this subtle problem is to let the server
230           add the trailing slash automatically. To do this
231           correctly we have to use an external redirect, so the
232           browser correctly requests subsequent images etc. If we
233           only did a internal rewrite, this would only work for the
234           directory page, but would go wrong when any images are
235           included into this page with relative URLs, because the
236           browser would request an in-lined object. For instance, a
237           request for <code>image.gif</code> in
238           <code>/~quux/foo/index.html</code> would become
239           <code>/~quux/image.gif</code> without the external
240           redirect!</p>
241
242           <p>So, to do this trick we write:</p>
243
244 <div class="example"><pre>
245 RewriteEngine  on
246 RewriteBase    /~quux/
247 RewriteRule    ^foo<strong>$</strong>  foo<strong>/</strong>  [<strong>R</strong>]
248 </pre></div>
249
250           <p>The crazy and lazy can even do the following in the
251           top-level <code>.htaccess</code> file of their homedir.
252           But notice that this creates some processing
253           overhead.</p>
254
255 <div class="example"><pre>
256 RewriteEngine  on
257 RewriteBase    /~quux/
258 RewriteCond    %{REQUEST_FILENAME}  <strong>-d</strong>
259 RewriteRule    ^(.+<strong>[^/]</strong>)$           $1<strong>/</strong>  [R]
260 </pre></div>
261         </dd>
262       </dl>
263
264     
265
266     <h3>Webcluster through Homogeneous URL Layout</h3>
267
268       
269
270       <dl>
271         <dt>Description:</dt>
272
273         <dd>
274           <p>We want to create a homogeneous and consistent URL
275           layout over all WWW servers on a Intranet webcluster, i.e.
276           all URLs (per definition server local and thus server
277           dependent!) become actually server <em>independent</em>!
278           What we want is to give the WWW namespace a consistent
279           server-independent layout: no URL should have to include
280           any physically correct target server. The cluster itself
281           should drive us automatically to the physical target
282           host.</p>
283         </dd>
284
285         <dt>Solution:</dt>
286
287         <dd>
288           <p>First, the knowledge of the target servers come from
289           (distributed) external maps which contain information
290           where our users, groups and entities stay. The have the
291           form</p>
292
293 <div class="example"><pre>
294 user1  server_of_user1
295 user2  server_of_user2
296 :      :
297 </pre></div>
298
299           <p>We put them into files <code>map.xxx-to-host</code>.
300           Second we need to instruct all servers to redirect URLs
301           of the forms</p>
302
303 <div class="example"><pre>
304 /u/user/anypath
305 /g/group/anypath
306 /e/entity/anypath
307 </pre></div>
308
309           <p>to</p>
310
311 <div class="example"><pre>
312 http://physical-host/u/user/anypath
313 http://physical-host/g/group/anypath
314 http://physical-host/e/entity/anypath
315 </pre></div>
316
317           <p>when the URL is not locally valid to a server. The
318           following ruleset does this for us by the help of the map
319           files (assuming that server0 is a default server which
320           will be used if a user has no entry in the map):</p>
321
322 <div class="example"><pre>
323 RewriteEngine on
324
325 RewriteMap      user-to-host   txt:/path/to/map.user-to-host
326 RewriteMap     group-to-host   txt:/path/to/map.group-to-host
327 RewriteMap    entity-to-host   txt:/path/to/map.entity-to-host
328
329 RewriteRule   ^/u/<strong>([^/]+)</strong>/?(.*)   http://<strong>${user-to-host:$1|server0}</strong>/u/$1/$2
330 RewriteRule   ^/g/<strong>([^/]+)</strong>/?(.*)  http://<strong>${group-to-host:$1|server0}</strong>/g/$1/$2
331 RewriteRule   ^/e/<strong>([^/]+)</strong>/?(.*) http://<strong>${entity-to-host:$1|server0}</strong>/e/$1/$2
332
333 RewriteRule   ^/([uge])/([^/]+)/?$          /$1/$2/.www/
334 RewriteRule   ^/([uge])/([^/]+)/([^.]+.+)   /$1/$2/.www/$3\
335 </pre></div>
336         </dd>
337       </dl>
338
339     
340
341     <h3>Move Homedirs to Different Webserver</h3>
342
343       
344
345       <dl>
346         <dt>Description:</dt>
347
348         <dd>
349           <p>Many webmasters have asked for a solution to the
350           following situation: They wanted to redirect just all
351           homedirs on a webserver to another webserver. They usually
352           need such things when establishing a newer webserver which
353           will replace the old one over time.</p>
354         </dd>
355
356         <dt>Solution:</dt>
357
358         <dd>
359           <p>The solution is trivial with <code class="module"><a href="../mod/mod_rewrite.html">mod_rewrite</a></code>.
360           On the old webserver we just redirect all
361           <code>/~user/anypath</code> URLs to
362           <code>http://newserver/~user/anypath</code>.</p>
363
364 <div class="example"><pre>
365 RewriteEngine on
366 RewriteRule   ^/~(.+)  http://<strong>newserver</strong>/~$1  [R,L]
367 </pre></div>
368         </dd>
369       </dl>
370
371     
372
373     <h3>Structured Homedirs</h3>
374
375       
376
377       <dl>
378         <dt>Description:</dt>
379
380         <dd>
381           <p>Some sites with thousands of users usually use a
382           structured homedir layout, i.e. each homedir is in a
383           subdirectory which begins for instance with the first
384           character of the username. So, <code>/~foo/anypath</code>
385           is <code>/home/<strong>f</strong>/foo/.www/anypath</code>
386           while <code>/~bar/anypath</code> is
387           <code>/home/<strong>b</strong>/bar/.www/anypath</code>.</p>
388         </dd>
389
390         <dt>Solution:</dt>
391
392         <dd>
393           <p>We use the following ruleset to expand the tilde URLs
394           into exactly the above layout.</p>
395
396 <div class="example"><pre>
397 RewriteEngine on
398 RewriteRule   ^/~(<strong>([a-z])</strong>[a-z0-9]+)(.*)  /home/<strong>$2</strong>/$1/.www$3
399 </pre></div>
400         </dd>
401       </dl>
402
403     
404
405     <h3>Filesystem Reorganization</h3>
406
407       
408
409       <dl>
410         <dt>Description:</dt>
411
412         <dd>
413           <p>This really is a hardcore example: a killer application
414           which heavily uses per-directory
415           <code>RewriteRules</code> to get a smooth look and feel
416           on the Web while its data structure is never touched or
417           adjusted. Background: <strong><em>net.sw</em></strong> is
418           my archive of freely available Unix software packages,
419           which I started to collect in 1992. It is both my hobby
420           and job to to this, because while I'm studying computer
421           science I have also worked for many years as a system and
422           network administrator in my spare time. Every week I need
423           some sort of software so I created a deep hierarchy of
424           directories where I stored the packages:</p>
425
426 <div class="example"><pre>
427 drwxrwxr-x   2 netsw  users    512 Aug  3 18:39 Audio/
428 drwxrwxr-x   2 netsw  users    512 Jul  9 14:37 Benchmark/
429 drwxrwxr-x  12 netsw  users    512 Jul  9 00:34 Crypto/
430 drwxrwxr-x   5 netsw  users    512 Jul  9 00:41 Database/
431 drwxrwxr-x   4 netsw  users    512 Jul 30 19:25 Dicts/
432 drwxrwxr-x  10 netsw  users    512 Jul  9 01:54 Graphic/
433 drwxrwxr-x   5 netsw  users    512 Jul  9 01:58 Hackers/
434 drwxrwxr-x   8 netsw  users    512 Jul  9 03:19 InfoSys/
435 drwxrwxr-x   3 netsw  users    512 Jul  9 03:21 Math/
436 drwxrwxr-x   3 netsw  users    512 Jul  9 03:24 Misc/
437 drwxrwxr-x   9 netsw  users    512 Aug  1 16:33 Network/
438 drwxrwxr-x   2 netsw  users    512 Jul  9 05:53 Office/
439 drwxrwxr-x   7 netsw  users    512 Jul  9 09:24 SoftEng/
440 drwxrwxr-x   7 netsw  users    512 Jul  9 12:17 System/
441 drwxrwxr-x  12 netsw  users    512 Aug  3 20:15 Typesetting/
442 drwxrwxr-x  10 netsw  users    512 Jul  9 14:08 X11/
443 </pre></div>
444
445           <p>In July 1996 I decided to make this archive public to
446           the world via a nice Web interface. "Nice" means that I
447           wanted to offer an interface where you can browse
448           directly through the archive hierarchy. And "nice" means
449           that I didn't wanted to change anything inside this
450           hierarchy - not even by putting some CGI scripts at the
451           top of it. Why? Because the above structure should be
452           later accessible via FTP as well, and I didn't want any
453           Web or CGI stuff to be there.</p>
454         </dd>
455
456         <dt>Solution:</dt>
457
458         <dd>
459           <p>The solution has two parts: The first is a set of CGI
460           scripts which create all the pages at all directory
461           levels on-the-fly. I put them under
462           <code>/e/netsw/.www/</code> as follows:</p>
463
464 <div class="example"><pre>
465 -rw-r--r--   1 netsw  users    1318 Aug  1 18:10 .wwwacl
466 drwxr-xr-x  18 netsw  users     512 Aug  5 15:51 DATA/
467 -rw-rw-rw-   1 netsw  users  372982 Aug  5 16:35 LOGFILE
468 -rw-r--r--   1 netsw  users     659 Aug  4 09:27 TODO
469 -rw-r--r--   1 netsw  users    5697 Aug  1 18:01 netsw-about.html
470 -rwxr-xr-x   1 netsw  users     579 Aug  2 10:33 netsw-access.pl
471 -rwxr-xr-x   1 netsw  users    1532 Aug  1 17:35 netsw-changes.cgi
472 -rwxr-xr-x   1 netsw  users    2866 Aug  5 14:49 netsw-home.cgi
473 drwxr-xr-x   2 netsw  users     512 Jul  8 23:47 netsw-img/
474 -rwxr-xr-x   1 netsw  users   24050 Aug  5 15:49 netsw-lsdir.cgi
475 -rwxr-xr-x   1 netsw  users    1589 Aug  3 18:43 netsw-search.cgi
476 -rwxr-xr-x   1 netsw  users    1885 Aug  1 17:41 netsw-tree.cgi
477 -rw-r--r--   1 netsw  users     234 Jul 30 16:35 netsw-unlimit.lst
478 </pre></div>
479
480           <p>The <code>DATA/</code> subdirectory holds the above
481           directory structure, i.e. the real
482           <strong><em>net.sw</em></strong> stuff and gets
483           automatically updated via <code>rdist</code> from time to
484           time. The second part of the problem remains: how to link
485           these two structures together into one smooth-looking URL
486           tree? We want to hide the <code>DATA/</code> directory
487           from the user while running the appropriate CGI scripts
488           for the various URLs. Here is the solution: first I put
489           the following into the per-directory configuration file
490           in the <code class="directive"><a href="../mod/core.html#documentroot">DocumentRoot</a></code>
491           of the server to rewrite the announced URL
492           <code>/net.sw/</code> to the internal path
493           <code>/e/netsw</code>:</p>
494
495 <div class="example"><pre>
496 RewriteRule  ^net.sw$       net.sw/        [R]
497 RewriteRule  ^net.sw/(.*)$  e/netsw/$1
498 </pre></div>
499
500           <p>The first rule is for requests which miss the trailing
501           slash! The second rule does the real thing. And then
502           comes the killer configuration which stays in the
503           per-directory config file
504           <code>/e/netsw/.www/.wwwacl</code>:</p>
505
506 <div class="example"><pre>
507 Options       ExecCGI FollowSymLinks Includes MultiViews
508
509 RewriteEngine on
510
511 #  we are reached via /net.sw/ prefix
512 RewriteBase   /net.sw/
513
514 #  first we rewrite the root dir to
515 #  the handling cgi script
516 RewriteRule   ^$                       netsw-home.cgi     [L]
517 RewriteRule   ^index\.html$            netsw-home.cgi     [L]
518
519 #  strip out the subdirs when
520 #  the browser requests us from perdir pages
521 RewriteRule   ^.+/(netsw-[^/]+/.+)$    $1                 [L]
522
523 #  and now break the rewriting for local files
524 RewriteRule   ^netsw-home\.cgi.*       -                  [L]
525 RewriteRule   ^netsw-changes\.cgi.*    -                  [L]
526 RewriteRule   ^netsw-search\.cgi.*     -                  [L]
527 RewriteRule   ^netsw-tree\.cgi$        -                  [L]
528 RewriteRule   ^netsw-about\.html$      -                  [L]
529 RewriteRule   ^netsw-img/.*$           -                  [L]
530
531 #  anything else is a subdir which gets handled
532 #  by another cgi script
533 RewriteRule   !^netsw-lsdir\.cgi.*     -                  [C]
534 RewriteRule   (.*)                     netsw-lsdir.cgi/$1
535 </pre></div>
536
537           <p>Some hints for interpretation:</p>
538
539           <ol>
540             <li>Notice the <code>L</code> (last) flag and no
541             substitution field ('<code>-</code>') in the forth part</li>
542
543             <li>Notice the <code>!</code> (not) character and
544             the <code>C</code> (chain) flag at the first rule
545             in the last part</li>
546
547             <li>Notice the catch-all pattern in the last rule</li>
548           </ol>
549         </dd>
550       </dl>
551
552     
553
554     <h3>NCSA imagemap to Apache <code>mod_imap</code></h3>
555
556       
557
558       <dl>
559         <dt>Description:</dt>
560
561         <dd>
562           <p>When switching from the NCSA webserver to the more
563           modern Apache webserver a lot of people want a smooth
564           transition. So they want pages which use their old NCSA
565           <code>imagemap</code> program to work under Apache with the
566           modern <code class="module"><a href="../mod/mod_imap.html">mod_imap</a></code>. The problem is that there
567           are a lot of hyperlinks around which reference the
568           <code>imagemap</code> program via
569           <code>/cgi-bin/imagemap/path/to/page.map</code>. Under
570           Apache this has to read just
571           <code>/path/to/page.map</code>.</p>
572         </dd>
573
574         <dt>Solution:</dt>
575
576         <dd>
577           <p>We use a global rule to remove the prefix on-the-fly for
578           all requests:</p>
579
580 <div class="example"><pre>
581 RewriteEngine  on
582 RewriteRule    ^/cgi-bin/imagemap(.*)  $1  [PT]
583 </pre></div>
584         </dd>
585       </dl>
586
587     
588
589     <h3>Search pages in more than one directory</h3>
590
591       
592
593       <dl>
594         <dt>Description:</dt>
595
596         <dd>
597           <p>Sometimes it is necessary to let the webserver search
598           for pages in more than one directory. Here MultiViews or
599           other techniques cannot help.</p>
600         </dd>
601
602         <dt>Solution:</dt>
603
604         <dd>
605           <p>We program a explicit ruleset which searches for the
606           files in the directories.</p>
607
608 <div class="example"><pre>
609 RewriteEngine on
610
611 #   first try to find it in custom/...
612 #   ...and if found stop and be happy:
613 RewriteCond         /your/docroot/<strong>dir1</strong>/%{REQUEST_FILENAME}  -f
614 RewriteRule  ^(.+)  /your/docroot/<strong>dir1</strong>/$1  [L]
615
616 #   second try to find it in pub/...
617 #   ...and if found stop and be happy:
618 RewriteCond         /your/docroot/<strong>dir2</strong>/%{REQUEST_FILENAME}  -f
619 RewriteRule  ^(.+)  /your/docroot/<strong>dir2</strong>/$1  [L]
620
621 #   else go on for other Alias or ScriptAlias directives,
622 #   etc.
623 RewriteRule   ^(.+)  -  [PT]
624 </pre></div>
625         </dd>
626       </dl>
627
628     
629
630     <h3>Set Environment Variables According To URL Parts</h3>
631
632       
633
634       <dl>
635         <dt>Description:</dt>
636
637         <dd>
638           <p>Perhaps you want to keep status information between
639           requests and use the URL to encode it. But you don't want
640           to use a CGI wrapper for all pages just to strip out this
641           information.</p>
642         </dd>
643
644         <dt>Solution:</dt>
645
646         <dd>
647           <p>We use a rewrite rule to strip out the status information
648           and remember it via an environment variable which can be
649           later dereferenced from within XSSI or CGI. This way a
650           URL <code>/foo/S=java/bar/</code> gets translated to
651           <code>/foo/bar/</code> and the environment variable named
652           <code>STATUS</code> is set to the value "java".</p>
653
654 <div class="example"><pre>
655 RewriteEngine on
656 RewriteRule   ^(.*)/<strong>S=([^/]+)</strong>/(.*)    $1/$3 [E=<strong>STATUS:$2</strong>]
657 </pre></div>
658         </dd>
659       </dl>
660
661     
662
663     <h3>Virtual User Hosts</h3>
664
665       
666
667       <dl>
668         <dt>Description:</dt>
669
670         <dd>
671           <p>Assume that you want to provide
672           <code>www.<strong>username</strong>.host.domain.com</code>
673           for the homepage of username via just DNS A records to the
674           same machine and without any virtualhosts on this
675           machine.</p>
676         </dd>
677
678         <dt>Solution:</dt>
679
680         <dd>
681           <p>For HTTP/1.0 requests there is no solution, but for
682           HTTP/1.1 requests which contain a Host: HTTP header we
683           can use the following ruleset to rewrite
684           <code>http://www.username.host.com/anypath</code>
685           internally to <code>/home/username/anypath</code>:</p>
686
687 <div class="example"><pre>
688 RewriteEngine on
689 RewriteCond   %{<strong>HTTP_HOST</strong>}                 ^www\.<strong>[^.]+</strong>\.host\.com$
690 RewriteRule   ^(.+)                        %{HTTP_HOST}$1          [C]
691 RewriteRule   ^www\.<strong>([^.]+)</strong>\.host\.com(.*) /home/<strong>$1</strong>$2
692 </pre></div>
693         </dd>
694       </dl>
695
696     
697
698     <h3>Redirect Homedirs For Foreigners</h3>
699
700       
701
702       <dl>
703         <dt>Description:</dt>
704
705         <dd>
706           <p>We want to redirect homedir URLs to another webserver
707           <code>www.somewhere.com</code> when the requesting user
708           does not stay in the local domain
709           <code>ourdomain.com</code>. This is sometimes used in
710           virtual host contexts.</p>
711         </dd>
712
713         <dt>Solution:</dt>
714
715         <dd>
716           <p>Just a rewrite condition:</p>
717
718 <div class="example"><pre>
719 RewriteEngine on
720 RewriteCond   %{REMOTE_HOST}  <strong>!^.+\.ourdomain\.com$</strong>
721 RewriteRule   ^(/~.+)         http://www.somewhere.com/$1 [R,L]
722 </pre></div>
723         </dd>
724       </dl>
725
726     
727
728     <h3>Redirect Failing URLs To Other Webserver</h3>
729
730       
731
732       <dl>
733         <dt>Description:</dt>
734
735         <dd>
736           <p>A typical FAQ about URL rewriting is how to redirect
737           failing requests on webserver A to webserver B. Usually
738           this is done via <code class="directive"><a href="../mod/core.html#errordocument">ErrorDocument</a></code> CGI-scripts in Perl, but
739           there is also a <code class="module"><a href="../mod/mod_rewrite.html">mod_rewrite</a></code> solution.
740           But notice that this performs more poorly than using an
741           <code class="directive"><a href="../mod/core.html#errordocument">ErrorDocument</a></code>
742           CGI-script!</p>
743         </dd>
744
745         <dt>Solution:</dt>
746
747         <dd>
748           <p>The first solution has the best performance but less
749           flexibility, and is less error safe:</p>
750
751 <div class="example"><pre>
752 RewriteEngine on
753 RewriteCond   /your/docroot/%{REQUEST_FILENAME} <strong>!-f</strong>
754 RewriteRule   ^(.+)                             http://<strong>webserverB</strong>.dom/$1
755 </pre></div>
756
757           <p>The problem here is that this will only work for pages
758           inside the <code class="directive"><a href="../mod/core.html#documentroot">DocumentRoot</a></code>. While you can add more
759           Conditions (for instance to also handle homedirs, etc.)
760           there is better variant:</p>
761
762 <div class="example"><pre>
763 RewriteEngine on
764 RewriteCond   %{REQUEST_URI} <strong>!-U</strong>
765 RewriteRule   ^(.+)          http://<strong>webserverB</strong>.dom/$1
766 </pre></div>
767
768           <p>This uses the URL look-ahead feature of <code class="module"><a href="../mod/mod_rewrite.html">mod_rewrite</a></code>.
769           The result is that this will work for all types of URLs
770           and is a safe way. But it does a performance impact on
771           the webserver, because for every request there is one
772           more internal subrequest. So, if your webserver runs on a
773           powerful CPU, use this one. If it is a slow machine, use
774           the first approach or better a <code class="directive"><a href="../mod/core.html#errordocument">ErrorDocument</a></code> CGI-script.</p>
775         </dd>
776       </dl>
777
778     
779
780     <h3>Extended Redirection</h3>
781
782       
783
784       <dl>
785         <dt>Description:</dt>
786
787         <dd>
788           <p>Sometimes we need more control (concerning the
789           character escaping mechanism) of URLs on redirects.
790           Usually the Apache kernels URL escape function also
791           escapes anchors, i.e. URLs like "<code>url#anchor</code>".
792           You cannot use this directly on redirects with
793           <code class="module"><a href="../mod/mod_rewrite.html">mod_rewrite</a></code> because the
794           <code>uri_escape()</code> function of Apache
795           would also escape the hash character.
796           How can we redirect to such a URL?</p>
797         </dd>
798
799         <dt>Solution:</dt>
800
801         <dd>
802           <p>We have to use a kludge by the use of a NPH-CGI script
803           which does the redirect itself. Because here no escaping
804           is done (NPH=non-parseable headers). First we introduce a
805           new URL scheme <code>xredirect:</code> by the following
806           per-server config-line (should be one of the last rewrite
807           rules):</p>
808
809 <div class="example"><pre>
810 RewriteRule ^xredirect:(.+) /path/to/nph-xredirect.cgi/$1 \
811             [T=application/x-httpd-cgi,L]
812 </pre></div>
813
814           <p>This forces all URLs prefixed with
815           <code>xredirect:</code> to be piped through the
816           <code>nph-xredirect.cgi</code> program. And this program
817           just looks like:</p>
818
819 <div class="example"><pre>
820 #!/path/to/perl
821 ##
822 ##  nph-xredirect.cgi -- NPH/CGI script for extended redirects
823 ##  Copyright (c) 1997 Ralf S. Engelschall, All Rights Reserved.
824 ##
825
826 $| = 1;
827 $url = $ENV{'PATH_INFO'};
828
829 print "HTTP/1.0 302 Moved Temporarily\n";
830 print "Server: $ENV{'SERVER_SOFTWARE'}\n";
831 print "Location: $url\n";
832 print "Content-type: text/html\n";
833 print "\n";
834 print "&lt;html&gt;\n";
835 print "&lt;head&gt;\n";
836 print "&lt;title&gt;302 Moved Temporarily (EXTENDED)&lt;/title&gt;\n";
837 print "&lt;/head&gt;\n";
838 print "&lt;body&gt;\n";
839 print "&lt;h1&gt;Moved Temporarily (EXTENDED)&lt;/h1&gt;\n";
840 print "The document has moved &lt;a HREF=\"$url\"&gt;here&lt;/a&gt;.&lt;p&gt;\n";
841 print "&lt;/body&gt;\n";
842 print "&lt;/html&gt;\n";
843
844 ##EOF##
845 </pre></div>
846
847           <p>This provides you with the functionality to do
848           redirects to all URL schemes, i.e. including the one
849           which are not directly accepted by <code class="module"><a href="../mod/mod_rewrite.html">mod_rewrite</a></code>.
850           For instance you can now also redirect to
851           <code>news:newsgroup</code> via</p>
852
853 <div class="example"><pre>
854 RewriteRule ^anyurl  xredirect:news:newsgroup
855 </pre></div>
856
857           <div class="note">Notice: You have not to put <code>[R]</code> or
858           <code>[R,L]</code> to the above rule because the
859           <code>xredirect:</code> need to be expanded later
860           by our special "pipe through" rule above.</div>
861         </dd>
862       </dl>
863
864     
865
866     <h3>Archive Access Multiplexer</h3>
867
868       
869
870       <dl>
871         <dt>Description:</dt>
872
873         <dd>
874           <p>Do you know the great CPAN (Comprehensive Perl Archive
875           Network) under <a href="http://www.perl.com/CPAN">http://www.perl.com/CPAN</a>?
876           This does a redirect to one of several FTP servers around
877           the world which carry a CPAN mirror and is approximately
878           near the location of the requesting client. Actually this
879           can be called an FTP access multiplexing service. While
880           CPAN runs via CGI scripts, how can a similar approach
881           implemented via <code class="module"><a href="../mod/mod_rewrite.html">mod_rewrite</a></code>?</p>
882         </dd>
883
884         <dt>Solution:</dt>
885
886         <dd>
887           <p>First we notice that from version 3.0.0
888           <code class="module"><a href="../mod/mod_rewrite.html">mod_rewrite</a></code> can
889           also use the "<code>ftp:</code>" scheme on redirects.
890           And second, the location approximation can be done by a
891           <code class="directive"><a href="../mod/mod_rewrite.html#rewritemap">RewriteMap</a></code>
892           over the top-level domain of the client.
893           With a tricky chained ruleset we can use this top-level
894           domain as a key to our multiplexing map.</p>
895
896 <div class="example"><pre>
897 RewriteEngine on
898 RewriteMap    multiplex                txt:/path/to/map.cxan
899 RewriteRule   ^/CxAN/(.*)              %{REMOTE_HOST}::$1                 [C]
900 RewriteRule   ^.+\.<strong>([a-zA-Z]+)</strong>::(.*)$  ${multiplex:<strong>$1</strong>|ftp.default.dom}$2  [R,L]
901 </pre></div>
902
903 <div class="example"><pre>
904 ##
905 ##  map.cxan -- Multiplexing Map for CxAN
906 ##
907
908 de        ftp://ftp.cxan.de/CxAN/
909 uk        ftp://ftp.cxan.uk/CxAN/
910 com       ftp://ftp.cxan.com/CxAN/
911  :
912 ##EOF##
913 </pre></div>
914         </dd>
915       </dl>
916
917     
918
919     <h3>Time-Dependent Rewriting</h3>
920
921       
922
923       <dl>
924         <dt>Description:</dt>
925
926         <dd>
927           <p>When tricks like time-dependent content should happen a
928           lot of webmasters still use CGI scripts which do for
929           instance redirects to specialized pages. How can it be done
930           via <code class="module"><a href="../mod/mod_rewrite.html">mod_rewrite</a></code>?</p>
931         </dd>
932
933         <dt>Solution:</dt>
934
935         <dd>
936           <p>There are a lot of variables named <code>TIME_xxx</code>
937           for rewrite conditions. In conjunction with the special
938           lexicographic comparison patterns <code>&lt;STRING</code>,
939           <code>&gt;STRING</code> and <code>=STRING</code> we can
940           do time-dependent redirects:</p>
941
942 <div class="example"><pre>
943 RewriteEngine on
944 RewriteCond   %{TIME_HOUR}%{TIME_MIN} &gt;0700
945 RewriteCond   %{TIME_HOUR}%{TIME_MIN} &lt;1900
946 RewriteRule   ^foo\.html$             foo.day.html
947 RewriteRule   ^foo\.html$             foo.night.html
948 </pre></div>
949
950           <p>This provides the content of <code>foo.day.html</code>
951           under the URL <code>foo.html</code> from
952           <code>07:00-19:00</code> and at the remaining time the
953           contents of <code>foo.night.html</code>. Just a nice
954           feature for a homepage...</p>
955         </dd>
956       </dl>
957
958     
959
960     <h3>Backward Compatibility for YYYY to XXXX migration</h3>
961
962       
963
964       <dl>
965         <dt>Description:</dt>
966
967         <dd>
968           <p>How can we make URLs backward compatible (still
969           existing virtually) after migrating <code>document.YYYY</code>
970           to <code>document.XXXX</code>, e.g. after translating a
971           bunch of <code>.html</code> files to <code>.phtml</code>?</p>
972         </dd>
973
974         <dt>Solution:</dt>
975
976         <dd>
977           <p>We just rewrite the name to its basename and test for
978           existence of the new extension. If it exists, we take
979           that name, else we rewrite the URL to its original state.</p>
980
981
982 <div class="example"><pre>
983 #   backward compatibility ruleset for
984 #   rewriting document.html to document.phtml
985 #   when and only when document.phtml exists
986 #   but no longer document.html
987 RewriteEngine on
988 RewriteBase   /~quux/
989 #   parse out basename, but remember the fact
990 RewriteRule   ^(.*)\.html$              $1      [C,E=WasHTML:yes]
991 #   rewrite to document.phtml if exists
992 RewriteCond   %{REQUEST_FILENAME}.phtml -f
993 RewriteRule   ^(.*)$ $1.phtml                   [S=1]
994 #   else reverse the previous basename cutout
995 RewriteCond   %{ENV:WasHTML}            ^yes$
996 RewriteRule   ^(.*)$ $1.html
997 </pre></div>
998         </dd>
999       </dl>
1000
1001     
1002
1003   </div><div class="top"><a href="#page-header"><img alt="top" src="../images/up.gif" /></a></div>
1004 <div class="section">
1005 <h2><a name="content" id="content">Content Handling</a></h2>
1006
1007     
1008
1009     <h3>From Old to New (intern)</h3>
1010
1011       
1012
1013       <dl>
1014         <dt>Description:</dt>
1015
1016         <dd>
1017           <p>Assume we have recently renamed the page
1018           <code>foo.html</code> to <code>bar.html</code> and now want
1019           to provide the old URL for backward compatibility. Actually
1020           we want that users of the old URL even not recognize that
1021           the pages was renamed.</p>
1022         </dd>
1023
1024         <dt>Solution:</dt>
1025
1026         <dd>
1027           <p>We rewrite the old URL to the new one internally via the
1028           following rule:</p>
1029
1030 <div class="example"><pre>
1031 RewriteEngine  on
1032 RewriteBase    /~quux/
1033 RewriteRule    ^<strong>foo</strong>\.html$  <strong>bar</strong>.html
1034 </pre></div>
1035         </dd>
1036       </dl>
1037
1038     
1039
1040     <h3>From Old to New (extern)</h3>
1041
1042       
1043
1044       <dl>
1045         <dt>Description:</dt>
1046
1047         <dd>
1048           <p>Assume again that we have recently renamed the page
1049           <code>foo.html</code> to <code>bar.html</code> and now want
1050           to provide the old URL for backward compatibility. But this
1051           time we want that the users of the old URL get hinted to
1052           the new one, i.e. their browsers Location field should
1053           change, too.</p>
1054         </dd>
1055
1056         <dt>Solution:</dt>
1057
1058         <dd>
1059           <p>We force a HTTP redirect to the new URL which leads to a
1060           change of the browsers and thus the users view:</p>
1061
1062 <div class="example"><pre>
1063 RewriteEngine  on
1064 RewriteBase    /~quux/
1065 RewriteRule    ^<strong>foo</strong>\.html$  <strong>bar</strong>.html  [<strong>R</strong>]
1066 </pre></div>
1067         </dd>
1068       </dl>
1069
1070     
1071
1072     <h3>Browser Dependent Content</h3>
1073
1074       
1075
1076       <dl>
1077         <dt>Description:</dt>
1078
1079         <dd>
1080           <p>At least for important top-level pages it is sometimes
1081           necessary to provide the optimum of browser dependent
1082           content, i.e. one has to provide a maximum version for the
1083           latest Netscape variants, a minimum version for the Lynx
1084           browsers and a average feature version for all others.</p>
1085         </dd>
1086
1087         <dt>Solution:</dt>
1088
1089         <dd>
1090           <p>We cannot use content negotiation because the browsers do
1091           not provide their type in that form. Instead we have to
1092           act on the HTTP header "User-Agent". The following condig
1093           does the following: If the HTTP header "User-Agent"
1094           begins with "Mozilla/3", the page <code>foo.html</code>
1095           is rewritten to <code>foo.NS.html</code> and and the
1096           rewriting stops. If the browser is "Lynx" or "Mozilla" of
1097           version 1 or 2 the URL becomes <code>foo.20.html</code>.
1098           All other browsers receive page <code>foo.32.html</code>.
1099           This is done by the following ruleset:</p>
1100
1101 <div class="example"><pre>
1102 RewriteCond %{HTTP_USER_AGENT}  ^<strong>Mozilla/3</strong>.*
1103 RewriteRule ^foo\.html$         foo.<strong>NS</strong>.html          [<strong>L</strong>]
1104
1105 RewriteCond %{HTTP_USER_AGENT}  ^<strong>Lynx/</strong>.*         [OR]
1106 RewriteCond %{HTTP_USER_AGENT}  ^<strong>Mozilla/[12]</strong>.*
1107 RewriteRule ^foo\.html$         foo.<strong>20</strong>.html          [<strong>L</strong>]
1108
1109 RewriteRule ^foo\.html$         foo.<strong>32</strong>.html          [<strong>L</strong>]
1110 </pre></div>
1111         </dd>
1112       </dl>
1113
1114     
1115
1116     <h3>Dynamic Mirror</h3>
1117
1118       
1119
1120       <dl>
1121         <dt>Description:</dt>
1122
1123         <dd>
1124           <p>Assume there are nice webpages on remote hosts we want
1125           to bring into our namespace. For FTP servers we would use
1126           the <code>mirror</code> program which actually maintains an
1127           explicit up-to-date copy of the remote data on the local
1128           machine. For a webserver we could use the program
1129           <code>webcopy</code> which acts similar via HTTP. But both
1130           techniques have one major drawback: The local copy is
1131           always just as up-to-date as often we run the program. It
1132           would be much better if the mirror is not a static one we
1133           have to establish explicitly. Instead we want a dynamic
1134           mirror with data which gets updated automatically when
1135           there is need (updated data on the remote host).</p>
1136         </dd>
1137
1138         <dt>Solution:</dt>
1139
1140         <dd>
1141           <p>To provide this feature we map the remote webpage or even
1142           the complete remote webarea to our namespace by the use
1143           of the <dfn>Proxy Throughput</dfn> feature
1144           (flag <code>[P]</code>):</p>
1145
1146 <div class="example"><pre>
1147 RewriteEngine  on
1148 RewriteBase    /~quux/
1149 RewriteRule    ^<strong>hotsheet/</strong>(.*)$  <strong>http://www.tstimpreso.com/hotsheet/</strong>$1  [<strong>P</strong>]
1150 </pre></div>
1151
1152 <div class="example"><pre>
1153 RewriteEngine  on
1154 RewriteBase    /~quux/
1155 RewriteRule    ^<strong>usa-news\.html</strong>$   <strong>http://www.quux-corp.com/news/index.html</strong>  [<strong>P</strong>]
1156 </pre></div>
1157         </dd>
1158       </dl>
1159
1160     
1161
1162     <h3>Reverse Dynamic Mirror</h3>
1163
1164       
1165
1166       <dl>
1167         <dt>Description:</dt>
1168
1169         <dd>...</dd>
1170
1171         <dt>Solution:</dt>
1172
1173         <dd>
1174 <div class="example"><pre>
1175 RewriteEngine on
1176 RewriteCond   /mirror/of/remotesite/$1           -U
1177 RewriteRule   ^http://www\.remotesite\.com/(.*)$ /mirror/of/remotesite/$1
1178 </pre></div>
1179         </dd>
1180       </dl>
1181
1182     
1183
1184     <h3>Retrieve Missing Data from Intranet</h3>
1185
1186       
1187
1188       <dl>
1189         <dt>Description:</dt>
1190
1191         <dd>
1192           <p>This is a tricky way of virtually running a corporate
1193           (external) Internet webserver
1194           (<code>www.quux-corp.dom</code>), while actually keeping
1195           and maintaining its data on a (internal) Intranet webserver
1196           (<code>www2.quux-corp.dom</code>) which is protected by a
1197           firewall. The trick is that on the external webserver we
1198           retrieve the requested data on-the-fly from the internal
1199           one.</p>
1200         </dd>
1201
1202         <dt>Solution:</dt>
1203
1204         <dd>
1205           <p>First, we have to make sure that our firewall still
1206           protects the internal webserver and that only the
1207           external webserver is allowed to retrieve data from it.
1208           For a packet-filtering firewall we could for instance
1209           configure a firewall ruleset like the following:</p>
1210
1211 <div class="example"><pre>
1212 <strong>ALLOW</strong> Host www.quux-corp.dom Port &gt;1024 --&gt; Host www2.quux-corp.dom Port <strong>80</strong>
1213 <strong>DENY</strong>  Host *                 Port *     --&gt; Host www2.quux-corp.dom Port <strong>80</strong>
1214 </pre></div>
1215
1216           <p>Just adjust it to your actual configuration syntax.
1217           Now we can establish the <code class="module"><a href="../mod/mod_rewrite.html">mod_rewrite</a></code>
1218           rules which request the missing data in the background
1219           through the proxy throughput feature:</p>
1220
1221 <div class="example"><pre>
1222 RewriteRule ^/~([^/]+)/?(.*)          /home/$1/.www/$2
1223 RewriteCond %{REQUEST_FILENAME}       <strong>!-f</strong>
1224 RewriteCond %{REQUEST_FILENAME}       <strong>!-d</strong>
1225 RewriteRule ^/home/([^/]+)/.www/?(.*) http://<strong>www2</strong>.quux-corp.dom/~$1/pub/$2 [<strong>P</strong>]
1226 </pre></div>
1227         </dd>
1228       </dl>
1229
1230     
1231
1232     <h3>Load Balancing</h3>
1233
1234       
1235
1236       <dl>
1237         <dt>Description:</dt>
1238
1239         <dd>
1240           <p>Suppose we want to load balance the traffic to
1241           <code>www.foo.com</code> over <code>www[0-5].foo.com</code>
1242           (a total of 6 servers). How can this be done?</p>
1243         </dd>
1244
1245         <dt>Solution:</dt>
1246
1247         <dd>
1248           <p>There are a lot of possible solutions for this problem.
1249           We will discuss first a commonly known DNS-based variant
1250           and then the special one with <code class="module"><a href="../mod/mod_rewrite.html">mod_rewrite</a></code>:</p>
1251
1252           <ol>
1253             <li>
1254               <strong>DNS Round-Robin</strong>
1255
1256               <p>The simplest method for load-balancing is to use
1257               the DNS round-robin feature of <code>BIND</code>.
1258               Here you just configure <code>www[0-9].foo.com</code>
1259               as usual in your DNS with A(address) records, e.g.</p>
1260
1261 <div class="example"><pre>
1262 www0   IN  A       1.2.3.1
1263 www1   IN  A       1.2.3.2
1264 www2   IN  A       1.2.3.3
1265 www3   IN  A       1.2.3.4
1266 www4   IN  A       1.2.3.5
1267 www5   IN  A       1.2.3.6
1268 </pre></div>
1269
1270               <p>Then you additionally add the following entry:</p>
1271
1272 <div class="example"><pre>
1273 www    IN  CNAME   www0.foo.com.
1274        IN  CNAME   www1.foo.com.
1275        IN  CNAME   www2.foo.com.
1276        IN  CNAME   www3.foo.com.
1277        IN  CNAME   www4.foo.com.
1278        IN  CNAME   www5.foo.com.
1279        IN  CNAME   www6.foo.com.
1280 </pre></div>
1281
1282               <p>Notice that this seems wrong, but is actually an
1283               intended feature of <code>BIND</code> and can be used
1284               in this way. However, now when <code>www.foo.com</code> gets
1285               resolved, <code>BIND</code> gives out <code>www0-www6</code>
1286               - but in a slightly permutated/rotated order every time.
1287               This way the clients are spread over the various
1288               servers. But notice that this not a perfect load
1289               balancing scheme, because DNS resolve information
1290               gets cached by the other nameservers on the net, so
1291               once a client has resolved <code>www.foo.com</code>
1292               to a particular <code>wwwN.foo.com</code>, all
1293               subsequent requests also go to this particular name
1294               <code>wwwN.foo.com</code>. But the final result is
1295               ok, because the total sum of the requests are really
1296               spread over the various webservers.</p>
1297             </li>
1298
1299             <li>
1300               <strong>DNS Load-Balancing</strong>
1301
1302               <p>A sophisticated DNS-based method for
1303               load-balancing is to use the program
1304               <code>lbnamed</code> which can be found at <a href="http://www.stanford.edu/~schemers/docs/lbnamed/lbnamed.html">
1305               http://www.stanford.edu/~schemers/docs/lbnamed/lbnamed.html</a>.
1306               It is a Perl 5 program in conjunction with auxilliary
1307               tools which provides a real load-balancing for
1308               DNS.</p>
1309             </li>
1310
1311             <li>
1312               <strong>Proxy Throughput Round-Robin</strong>
1313
1314               <p>In this variant we use <code class="module"><a href="../mod/mod_rewrite.html">mod_rewrite</a></code>
1315               and its proxy throughput feature. First we dedicate
1316               <code>www0.foo.com</code> to be actually
1317               <code>www.foo.com</code> by using a single</p>
1318
1319 <div class="example"><pre>
1320 www    IN  CNAME   www0.foo.com.
1321 </pre></div>
1322
1323               <p>entry in the DNS. Then we convert
1324               <code>www0.foo.com</code> to a proxy-only server,
1325               i.e. we configure this machine so all arriving URLs
1326               are just pushed through the internal proxy to one of
1327               the 5 other servers (<code>www1-www5</code>). To
1328               accomplish this we first establish a ruleset which
1329               contacts a load balancing script <code>lb.pl</code>
1330               for all URLs.</p>
1331
1332 <div class="example"><pre>
1333 RewriteEngine on
1334 RewriteMap    lb      prg:/path/to/lb.pl
1335 RewriteRule   ^/(.+)$ ${lb:$1}           [P,L]
1336 </pre></div>
1337
1338               <p>Then we write <code>lb.pl</code>:</p>
1339
1340 <div class="example"><pre>
1341 #!/path/to/perl
1342 ##
1343 ##  lb.pl -- load balancing script
1344 ##
1345
1346 $| = 1;
1347
1348 $name   = "www";     # the hostname base
1349 $first  = 1;         # the first server (not 0 here, because 0 is myself)
1350 $last   = 5;         # the last server in the round-robin
1351 $domain = "foo.dom"; # the domainname
1352
1353 $cnt = 0;
1354 while (&lt;STDIN&gt;) {
1355     $cnt = (($cnt+1) % ($last+1-$first));
1356     $server = sprintf("%s%d.%s", $name, $cnt+$first, $domain);
1357     print "http://$server/$_";
1358 }
1359
1360 ##EOF##
1361 </pre></div>
1362
1363               <div class="note">A last notice: Why is this useful? Seems like
1364               <code>www0.foo.com</code> still is overloaded? The
1365               answer is yes, it is overloaded, but with plain proxy
1366               throughput requests, only! All SSI, CGI, ePerl, etc.
1367               processing is completely done on the other machines.
1368               This is the essential point.</div>
1369             </li>
1370
1371             <li>
1372               <strong>Hardware/TCP Round-Robin</strong>
1373
1374               <p>There is a hardware solution available, too. Cisco
1375               has a beast called LocalDirector which does a load
1376               balancing at the TCP/IP level. Actually this is some
1377               sort of a circuit level gateway in front of a
1378               webcluster. If you have enough money and really need
1379               a solution with high performance, use this one.</p>
1380             </li>
1381           </ol>
1382         </dd>
1383       </dl>
1384
1385     
1386
1387     <h3>New MIME-type, New Service</h3>
1388
1389       
1390
1391       <dl>
1392         <dt>Description:</dt>
1393
1394         <dd>
1395           <p>On the net there are a lot of nifty CGI programs. But
1396           their usage is usually boring, so a lot of webmaster
1397           don't use them. Even Apache's Action handler feature for
1398           MIME-types is only appropriate when the CGI programs
1399           don't need special URLs (actually <code>PATH_INFO</code>
1400           and <code>QUERY_STRINGS</code>) as their input. First,
1401           let us configure a new file type with extension
1402           <code>.scgi</code> (for secure CGI) which will be processed
1403           by the popular <code>cgiwrap</code> program. The problem
1404           here is that for instance we use a Homogeneous URL Layout
1405           (see above) a file inside the user homedirs has the URL
1406           <code>/u/user/foo/bar.scgi</code>. But
1407           <code>cgiwrap</code> needs the URL in the form
1408           <code>/~user/foo/bar.scgi/</code>. The following rule
1409           solves the problem:</p>
1410
1411 <div class="example"><pre>
1412 RewriteRule ^/[uge]/<strong>([^/]+)</strong>/\.www/(.+)\.scgi(.*) ...
1413 ... /internal/cgi/user/cgiwrap/~<strong>$1</strong>/$2.scgi$3  [NS,<strong>T=application/x-http-cgi</strong>]
1414 </pre></div>
1415
1416           <p>Or assume we have some more nifty programs:
1417           <code>wwwlog</code> (which displays the
1418           <code>access.log</code> for a URL subtree and
1419           <code>wwwidx</code> (which runs Glimpse on a URL
1420           subtree). We have to provide the URL area to these
1421           programs so they know on which area they have to act on.
1422           But usually this ugly, because they are all the times
1423           still requested from that areas, i.e. typically we would
1424           run the <code>swwidx</code> program from within
1425           <code>/u/user/foo/</code> via hyperlink to</p>
1426
1427 <div class="example"><pre>
1428 /internal/cgi/user/swwidx?i=/u/user/foo/
1429 </pre></div>
1430
1431           <p>which is ugly. Because we have to hard-code
1432           <strong>both</strong> the location of the area
1433           <strong>and</strong> the location of the CGI inside the
1434           hyperlink. When we have to reorganize the area, we spend a
1435           lot of time changing the various hyperlinks.</p>
1436         </dd>
1437
1438         <dt>Solution:</dt>
1439
1440         <dd>
1441           <p>The solution here is to provide a special new URL format
1442           which automatically leads to the proper CGI invocation.
1443           We configure the following:</p>
1444
1445 <div class="example"><pre>
1446 RewriteRule   ^/([uge])/([^/]+)(/?.*)/\*  /internal/cgi/user/wwwidx?i=/$1/$2$3/
1447 RewriteRule   ^/([uge])/([^/]+)(/?.*):log /internal/cgi/user/wwwlog?f=/$1/$2$3
1448 </pre></div>
1449
1450           <p>Now the hyperlink to search at
1451           <code>/u/user/foo/</code> reads only</p>
1452
1453 <div class="example"><pre>
1454 HREF="*"
1455 </pre></div>
1456
1457           <p>which internally gets automatically transformed to</p>
1458
1459 <div class="example"><pre>
1460 /internal/cgi/user/wwwidx?i=/u/user/foo/
1461 </pre></div>
1462
1463           <p>The same approach leads to an invocation for the
1464           access log CGI program when the hyperlink
1465           <code>:log</code> gets used.</p>
1466         </dd>
1467       </dl>
1468
1469     
1470
1471     <h3>From Static to Dynamic</h3>
1472
1473       
1474
1475       <dl>
1476         <dt>Description:</dt>
1477
1478         <dd>
1479           <p>How can we transform a static page
1480           <code>foo.html</code> into a dynamic variant
1481           <code>foo.cgi</code> in a seamless way, i.e. without notice
1482           by the browser/user.</p>
1483         </dd>
1484
1485         <dt>Solution:</dt>
1486
1487         <dd>
1488           <p>We just rewrite the URL to the CGI-script and force the
1489           correct MIME-type so it gets really run as a CGI-script.
1490           This way a request to <code>/~quux/foo.html</code>
1491           internally leads to the invocation of
1492           <code>/~quux/foo.cgi</code>.</p>
1493
1494 <div class="example"><pre>
1495 RewriteEngine  on
1496 RewriteBase    /~quux/
1497 RewriteRule    ^foo\.<strong>html</strong>$  foo.<strong>cgi</strong>  [T=<strong>application/x-httpd-cgi</strong>]
1498 </pre></div>
1499         </dd>
1500       </dl>
1501
1502     
1503
1504     <h3>On-the-fly Content-Regeneration</h3>
1505
1506       
1507
1508       <dl>
1509         <dt>Description:</dt>
1510
1511         <dd>
1512           <p>Here comes a really esoteric feature: Dynamically
1513           generated but statically served pages, i.e. pages should be
1514           delivered as pure static pages (read from the filesystem
1515           and just passed through), but they have to be generated
1516           dynamically by the webserver if missing. This way you can
1517           have CGI-generated pages which are statically served unless
1518           one (or a cronjob) removes the static contents. Then the
1519           contents gets refreshed.</p>
1520         </dd>
1521
1522         <dt>Solution:</dt>
1523
1524         <dd>
1525           This is done via the following ruleset:
1526
1527 <div class="example"><pre>
1528 RewriteCond %{REQUEST_FILENAME}   <strong>!-s</strong>
1529 RewriteRule ^page\.<strong>html</strong>$          page.<strong>cgi</strong>   [T=application/x-httpd-cgi,L]
1530 </pre></div>
1531
1532           <p>Here a request to <code>page.html</code> leads to a
1533           internal run of a corresponding <code>page.cgi</code> if
1534           <code>page.html</code> is still missing or has filesize
1535           null. The trick here is that <code>page.cgi</code> is a
1536           usual CGI script which (additionally to its <code>STDOUT</code>)
1537           writes its output to the file <code>page.html</code>.
1538           Once it was run, the server sends out the data of
1539           <code>page.html</code>. When the webmaster wants to force
1540           a refresh the contents, he just removes
1541           <code>page.html</code> (usually done by a cronjob).</p>
1542         </dd>
1543       </dl>
1544
1545     
1546
1547     <h3>Document With Autorefresh</h3>
1548
1549       
1550
1551       <dl>
1552         <dt>Description:</dt>
1553
1554         <dd>
1555           <p>Wouldn't it be nice while creating a complex webpage if
1556           the webbrowser would automatically refresh the page every
1557           time we write a new version from within our editor?
1558           Impossible?</p>
1559         </dd>
1560
1561         <dt>Solution:</dt>
1562
1563         <dd>
1564           <p>No! We just combine the MIME multipart feature, the
1565           webserver NPH feature and the URL manipulation power of
1566           <code class="module"><a href="../mod/mod_rewrite.html">mod_rewrite</a></code>. First, we establish a new
1567           URL feature: Adding just <code>:refresh</code> to any
1568           URL causes this to be refreshed every time it gets
1569           updated on the filesystem.</p>
1570
1571 <div class="example"><pre>
1572 RewriteRule   ^(/[uge]/[^/]+/?.*):refresh  /internal/cgi/apache/nph-refresh?f=$1
1573 </pre></div>
1574
1575           <p>Now when we reference the URL</p>
1576
1577 <div class="example"><pre>
1578 /u/foo/bar/page.html:refresh
1579 </pre></div>
1580
1581           <p>this leads to the internal invocation of the URL</p>
1582
1583 <div class="example"><pre>
1584 /internal/cgi/apache/nph-refresh?f=/u/foo/bar/page.html
1585 </pre></div>
1586
1587           <p>The only missing part is the NPH-CGI script. Although
1588           one would usually say "left as an exercise to the reader"
1589           ;-) I will provide this, too.</p>
1590
1591 <div class="example"><pre>
1592 #!/sw/bin/perl
1593 ##
1594 ##  nph-refresh -- NPH/CGI script for auto refreshing pages
1595 ##  Copyright (c) 1997 Ralf S. Engelschall, All Rights Reserved.
1596 ##
1597 $| = 1;
1598
1599 #   split the QUERY_STRING variable
1600 @pairs = split(/&amp;/, $ENV{'QUERY_STRING'});
1601 foreach $pair (@pairs) {
1602     ($name, $value) = split(/=/, $pair);
1603     $name =~ tr/A-Z/a-z/;
1604     $name = 'QS_' . $name;
1605     $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
1606     eval "\$$name = \"$value\"";
1607 }
1608 $QS_s = 1 if ($QS_s eq '');
1609 $QS_n = 3600 if ($QS_n eq '');
1610 if ($QS_f eq '') {
1611     print "HTTP/1.0 200 OK\n";
1612     print "Content-type: text/html\n\n";
1613     print "&amp;lt;b&amp;gt;ERROR&amp;lt;/b&amp;gt;: No file given\n";
1614     exit(0);
1615 }
1616 if (! -f $QS_f) {
1617     print "HTTP/1.0 200 OK\n";
1618     print "Content-type: text/html\n\n";
1619     print "&amp;lt;b&amp;gt;ERROR&amp;lt;/b&amp;gt;: File $QS_f not found\n";
1620     exit(0);
1621 }
1622
1623 sub print_http_headers_multipart_begin {
1624     print "HTTP/1.0 200 OK\n";
1625     $bound = "ThisRandomString12345";
1626     print "Content-type: multipart/x-mixed-replace;boundary=$bound\n";
1627     &amp;print_http_headers_multipart_next;
1628 }
1629
1630 sub print_http_headers_multipart_next {
1631     print "\n--$bound\n";
1632 }
1633
1634 sub print_http_headers_multipart_end {
1635     print "\n--$bound--\n";
1636 }
1637
1638 sub displayhtml {
1639     local($buffer) = @_;
1640     $len = length($buffer);
1641     print "Content-type: text/html\n";
1642     print "Content-length: $len\n\n";
1643     print $buffer;
1644 }
1645
1646 sub readfile {
1647     local($file) = @_;
1648     local(*FP, $size, $buffer, $bytes);
1649     ($x, $x, $x, $x, $x, $x, $x, $size) = stat($file);
1650     $size = sprintf("%d", $size);
1651     open(FP, "&amp;lt;$file");
1652     $bytes = sysread(FP, $buffer, $size);
1653     close(FP);
1654     return $buffer;
1655 }
1656
1657 $buffer = &amp;readfile($QS_f);
1658 &amp;print_http_headers_multipart_begin;
1659 &amp;displayhtml($buffer);
1660
1661 sub mystat {
1662     local($file) = $_[0];
1663     local($time);
1664
1665     ($x, $x, $x, $x, $x, $x, $x, $x, $x, $mtime) = stat($file);
1666     return $mtime;
1667 }
1668
1669 $mtimeL = &amp;mystat($QS_f);
1670 $mtime = $mtime;
1671 for ($n = 0; $n &amp;lt; $QS_n; $n++) {
1672     while (1) {
1673         $mtime = &amp;mystat($QS_f);
1674         if ($mtime ne $mtimeL) {
1675             $mtimeL = $mtime;
1676             sleep(2);
1677             $buffer = &amp;readfile($QS_f);
1678             &amp;print_http_headers_multipart_next;
1679             &amp;displayhtml($buffer);
1680             sleep(5);
1681             $mtimeL = &amp;mystat($QS_f);
1682             last;
1683         }
1684         sleep($QS_s);
1685     }
1686 }
1687
1688 &amp;print_http_headers_multipart_end;
1689
1690 exit(0);
1691
1692 ##EOF##
1693 </pre></div>
1694         </dd>
1695       </dl>
1696
1697     
1698
1699     <h3>Mass Virtual Hosting</h3>
1700
1701       
1702
1703       <dl>
1704         <dt>Description:</dt>
1705
1706         <dd>
1707           <p>The <code class="directive"><a href="../mod/core.html#virtualhost">&lt;VirtualHost&gt;</a></code> feature of Apache is nice
1708           and works great when you just have a few dozens
1709           virtual hosts. But when you are an ISP and have hundreds of
1710           virtual hosts to provide this feature is not the best
1711           choice.</p>
1712         </dd>
1713
1714         <dt>Solution:</dt>
1715
1716         <dd>
1717           <p>To provide this feature we map the remote webpage or even
1718           the complete remote webarea to our namespace by the use
1719           of the <dfn>Proxy Throughput</dfn> feature (flag <code>[P]</code>):</p>
1720
1721 <div class="example"><pre>
1722 ##
1723 ##  vhost.map
1724 ##
1725 www.vhost1.dom:80  /path/to/docroot/vhost1
1726 www.vhost2.dom:80  /path/to/docroot/vhost2
1727      :
1728 www.vhostN.dom:80  /path/to/docroot/vhostN
1729 </pre></div>
1730
1731 <div class="example"><pre>
1732 ##
1733 ##  httpd.conf
1734 ##
1735     :
1736 #   use the canonical hostname on redirects, etc.
1737 UseCanonicalName on
1738
1739     :
1740 #   add the virtual host in front of the CLF-format
1741 CustomLog  /path/to/access_log  "%{VHOST}e %h %l %u %t \"%r\" %&gt;s %b"
1742     :
1743
1744 #   enable the rewriting engine in the main server
1745 RewriteEngine on
1746
1747 #   define two maps: one for fixing the URL and one which defines
1748 #   the available virtual hosts with their corresponding
1749 #   DocumentRoot.
1750 RewriteMap    lowercase    int:tolower
1751 RewriteMap    vhost        txt:/path/to/vhost.map
1752
1753 #   Now do the actual virtual host mapping
1754 #   via a huge and complicated single rule:
1755 #
1756 #   1. make sure we don't map for common locations
1757 RewriteCond   %{REQUEST_URI}  !^/commonurl1/.*
1758 RewriteCond   %{REQUEST_URI}  !^/commonurl2/.*
1759     :
1760 RewriteCond   %{REQUEST_URI}  !^/commonurlN/.*
1761 #
1762 #   2. make sure we have a Host header, because
1763 #      currently our approach only supports
1764 #      virtual hosting through this header
1765 RewriteCond   %{HTTP_HOST}  !^$
1766 #
1767 #   3. lowercase the hostname
1768 RewriteCond   ${lowercase:%{HTTP_HOST}|NONE}  ^(.+)$
1769 #
1770 #   4. lookup this hostname in vhost.map and
1771 #      remember it only when it is a path
1772 #      (and not "NONE" from above)
1773 RewriteCond   ${vhost:%1}  ^(/.*)$
1774 #
1775 #   5. finally we can map the URL to its docroot location
1776 #      and remember the virtual host for logging puposes
1777 RewriteRule   ^/(.*)$   %1/$1  [E=VHOST:${lowercase:%{HTTP_HOST}}]
1778     :
1779 </pre></div>
1780         </dd>
1781       </dl>
1782
1783     
1784
1785   </div><div class="top"><a href="#page-header"><img alt="top" src="../images/up.gif" /></a></div>
1786 <div class="section">
1787 <h2><a name="access" id="access">Access Restriction</a></h2>
1788
1789     
1790
1791     <h3>Blocking of Robots</h3>
1792
1793       
1794
1795       <dl>
1796         <dt>Description:</dt>
1797
1798         <dd>
1799           <p>How can we block a really annoying robot from
1800           retrieving pages of a specific webarea? A
1801           <code>/robots.txt</code> file containing entries of the
1802           "Robot Exclusion Protocol" is typically not enough to get
1803           rid of such a robot.</p>
1804         </dd>
1805
1806         <dt>Solution:</dt>
1807
1808         <dd>
1809           <p>We use a ruleset which forbids the URLs of the webarea
1810           <code>/~quux/foo/arc/</code> (perhaps a very deep
1811           directory indexed area where the robot traversal would
1812           create big server load). We have to make sure that we
1813           forbid access only to the particular robot, i.e. just
1814           forbidding the host where the robot runs is not enough.
1815           This would block users from this host, too. We accomplish
1816           this by also matching the User-Agent HTTP header
1817           information.</p>
1818
1819 <div class="example"><pre>
1820 RewriteCond %{HTTP_USER_AGENT}   ^<strong>NameOfBadRobot</strong>.*
1821 RewriteCond %{REMOTE_ADDR}       ^<strong>123\.45\.67\.[8-9]</strong>$
1822 RewriteRule ^<strong>/~quux/foo/arc/</strong>.+   -   [<strong>F</strong>]
1823 </pre></div>
1824         </dd>
1825       </dl>
1826
1827     
1828
1829     <h3>Blocked Inline-Images</h3>
1830
1831       
1832
1833       <dl>
1834         <dt>Description:</dt>
1835
1836         <dd>
1837           <p>Assume we have under <code>http://www.quux-corp.de/~quux/</code>
1838           some pages with inlined GIF graphics. These graphics are
1839           nice, so others directly incorporate them via hyperlinks to
1840           their pages. We don't like this practice because it adds
1841           useless traffic to our server.</p>
1842         </dd>
1843
1844         <dt>Solution:</dt>
1845
1846         <dd>
1847           <p>While we cannot 100% protect the images from inclusion,
1848           we can at least restrict the cases where the browser
1849           sends a HTTP Referer header.</p>
1850
1851 <div class="example"><pre>
1852 RewriteCond %{HTTP_REFERER} <strong>!^$</strong>
1853 RewriteCond %{HTTP_REFERER} !^http://www.quux-corp.de/~quux/.*$ [NC]
1854 RewriteRule <strong>.*\.gif$</strong>        -                                    [F]
1855 </pre></div>
1856
1857 <div class="example"><pre>
1858 RewriteCond %{HTTP_REFERER}         !^$
1859 RewriteCond %{HTTP_REFERER}         !.*/foo-with-gif\.html$
1860 RewriteRule <strong>^inlined-in-foo\.gif$</strong>   -                        [F]
1861 </pre></div>
1862         </dd>
1863       </dl>
1864
1865     
1866
1867     <h3>Host Deny</h3>
1868
1869       
1870
1871       <dl>
1872         <dt>Description:</dt>
1873
1874         <dd>
1875           <p>How can we forbid a list of externally configured hosts
1876           from using our server?</p>
1877         </dd>
1878
1879         <dt>Solution:</dt>
1880
1881         <dd>
1882           <p>For Apache &gt;= 1.3b6:</p>
1883
1884 <div class="example"><pre>
1885 RewriteEngine on
1886 RewriteMap    hosts-deny  txt:/path/to/hosts.deny
1887 RewriteCond   ${hosts-deny:%{REMOTE_HOST}|NOT-FOUND} !=NOT-FOUND [OR]
1888 RewriteCond   ${hosts-deny:%{REMOTE_ADDR}|NOT-FOUND} !=NOT-FOUND
1889 RewriteRule   ^/.*  -  [F]
1890 </pre></div>
1891
1892           <p>For Apache &lt;= 1.3b6:</p>
1893
1894 <div class="example"><pre>
1895 RewriteEngine on
1896 RewriteMap    hosts-deny  txt:/path/to/hosts.deny
1897 RewriteRule   ^/(.*)$ ${hosts-deny:%{REMOTE_HOST}|NOT-FOUND}/$1
1898 RewriteRule   !^NOT-FOUND/.* - [F]
1899 RewriteRule   ^NOT-FOUND/(.*)$ ${hosts-deny:%{REMOTE_ADDR}|NOT-FOUND}/$1
1900 RewriteRule   !^NOT-FOUND/.* - [F]
1901 RewriteRule   ^NOT-FOUND/(.*)$ /$1
1902 </pre></div>
1903
1904 <div class="example"><pre>
1905 ##
1906 ##  hosts.deny
1907 ##
1908 ##  ATTENTION! This is a map, not a list, even when we treat it as such.
1909 ##             mod_rewrite parses it for key/value pairs, so at least a
1910 ##             dummy value "-" must be present for each entry.
1911 ##
1912
1913 193.102.180.41 -
1914 bsdti1.sdm.de  -
1915 192.76.162.40  -
1916 </pre></div>
1917         </dd>
1918       </dl>
1919
1920     
1921
1922     <h3>Proxy Deny</h3>
1923
1924       
1925
1926       <dl>
1927         <dt>Description:</dt>
1928
1929         <dd>
1930           <p>How can we forbid a certain host or even a user of a
1931           special host from using the Apache proxy?</p>
1932         </dd>
1933
1934         <dt>Solution:</dt>
1935
1936         <dd>
1937           <p>We first have to make sure <code class="module"><a href="../mod/mod_rewrite.html">mod_rewrite</a></code>
1938           is below(!) <code class="module"><a href="../mod/mod_proxy.html">mod_proxy</a></code> in the Configuration
1939           file when compiling the Apache webserver. This way it gets
1940           called <em>before</em> <code class="module"><a href="../mod/mod_proxy.html">mod_proxy</a></code>. Then we
1941           configure the following for a host-dependent deny...</p>
1942
1943 <div class="example"><pre>
1944 RewriteCond %{REMOTE_HOST} <strong>^badhost\.mydomain\.com$</strong>
1945 RewriteRule !^http://[^/.]\.mydomain.com.*  - [F]
1946 </pre></div>
1947
1948           <p>...and this one for a user@host-dependent deny:</p>
1949
1950 <div class="example"><pre>
1951 RewriteCond %{REMOTE_IDENT}@%{REMOTE_HOST}  <strong>^badguy@badhost\.mydomain\.com$</strong>
1952 RewriteRule !^http://[^/.]\.mydomain.com.*  - [F]
1953 </pre></div>
1954         </dd>
1955       </dl>
1956
1957     
1958
1959     <h3>Special Authentication Variant</h3>
1960
1961       
1962
1963       <dl>
1964         <dt>Description:</dt>
1965
1966         <dd>
1967           <p>Sometimes a very special authentication is needed, for
1968           instance a authentication which checks for a set of
1969           explicitly configured users. Only these should receive
1970           access and without explicit prompting (which would occur
1971           when using the Basic Auth via <code class="module"><a href="../mod/mod_auth.html">mod_auth</a></code>).</p>
1972         </dd>
1973
1974         <dt>Solution:</dt>
1975
1976         <dd>
1977           <p>We use a list of rewrite conditions to exclude all except
1978           our friends:</p>
1979
1980 <div class="example"><pre>
1981 RewriteCond %{REMOTE_IDENT}@%{REMOTE_HOST} <strong>!^friend1@client1.quux-corp\.com$</strong>
1982 RewriteCond %{REMOTE_IDENT}@%{REMOTE_HOST} <strong>!^friend2</strong>@client2.quux-corp\.com$
1983 RewriteCond %{REMOTE_IDENT}@%{REMOTE_HOST} <strong>!^friend3</strong>@client3.quux-corp\.com$
1984 RewriteRule ^/~quux/only-for-friends/      -                                 [F]
1985 </pre></div>
1986         </dd>
1987       </dl>
1988
1989     
1990
1991     <h3>Referer-based Deflector</h3>
1992
1993       
1994
1995       <dl>
1996         <dt>Description:</dt>
1997
1998         <dd>
1999           <p>How can we program a flexible URL Deflector which acts
2000           on the "Referer" HTTP header and can be configured with as
2001           many referring pages as we like?</p>
2002         </dd>
2003
2004         <dt>Solution:</dt>
2005
2006         <dd>
2007           <p>Use the following really tricky ruleset...</p>
2008
2009 <div class="example"><pre>
2010 RewriteMap  deflector txt:/path/to/deflector.map
2011
2012 RewriteCond %{HTTP_REFERER} !=""
2013 RewriteCond ${deflector:%{HTTP_REFERER}} ^-$
2014 RewriteRule ^.* %{HTTP_REFERER} [R,L]
2015
2016 RewriteCond %{HTTP_REFERER} !=""
2017 RewriteCond ${deflector:%{HTTP_REFERER}|NOT-FOUND} !=NOT-FOUND
2018 RewriteRule ^.* ${deflector:%{HTTP_REFERER}} [R,L]
2019 </pre></div>
2020
2021           <p>... in conjunction with a corresponding rewrite
2022           map:</p>
2023
2024 <div class="example"><pre>
2025 ##
2026 ##  deflector.map
2027 ##
2028
2029 http://www.badguys.com/bad/index.html    -
2030 http://www.badguys.com/bad/index2.html   -
2031 http://www.badguys.com/bad/index3.html   http://somewhere.com/
2032 </pre></div>
2033
2034           <p>This automatically redirects the request back to the
2035           referring page (when "<code>-</code>" is used as the value
2036           in the map) or to a specific URL (when an URL is specified
2037           in the map as the second argument).</p>
2038         </dd>
2039       </dl>
2040
2041     
2042
2043   </div><div class="top"><a href="#page-header"><img alt="top" src="../images/up.gif" /></a></div>
2044 <div class="section">
2045 <h2><a name="other" id="other">Other</a></h2>
2046
2047     
2048
2049     <h3>External Rewriting Engine</h3>
2050
2051       
2052
2053       <dl>
2054         <dt>Description:</dt>
2055
2056         <dd>
2057           <p>A FAQ: How can we solve the FOO/BAR/QUUX/etc.
2058           problem? There seems no solution by the use of
2059           <code class="module"><a href="../mod/mod_rewrite.html">mod_rewrite</a></code>...</p>
2060         </dd>
2061
2062         <dt>Solution:</dt>
2063
2064         <dd>
2065           <p>Use an external <code class="directive"><a href="../mod/mod_rewrite.html#rewritemap">RewriteMap</a></code>, i.e. a program which acts
2066           like a <code class="directive"><a href="../mod/mod_rewrite.html#rewritemap">RewriteMap</a></code>. It is run once on startup of Apache
2067           receives the requested URLs on <code>STDIN</code> and has
2068           to put the resulting (usually rewritten) URL on
2069           <code>STDOUT</code> (same order!).</p>
2070
2071 <div class="example"><pre>
2072 RewriteEngine on
2073 RewriteMap    quux-map       <strong>prg:</strong>/path/to/map.quux.pl
2074 RewriteRule   ^/~quux/(.*)$  /~quux/<strong>${quux-map:$1}</strong>
2075 </pre></div>
2076
2077 <div class="example"><pre>
2078 #!/path/to/perl
2079
2080 #   disable buffered I/O which would lead
2081 #   to deadloops for the Apache server
2082 $| = 1;
2083
2084 #   read URLs one per line from stdin and
2085 #   generate substitution URL on stdout
2086 while (&lt;&gt;) {
2087     s|^foo/|bar/|;
2088     print $_;
2089 }
2090 </pre></div>
2091
2092           <p>This is a demonstration-only example and just rewrites
2093           all URLs <code>/~quux/foo/...</code> to
2094           <code>/~quux/bar/...</code>. Actually you can program
2095           whatever you like. But notice that while such maps can be
2096           <strong>used</strong> also by an average user, only the
2097           system administrator can <strong>define</strong> it.</p>
2098         </dd>
2099       </dl>
2100
2101     
2102
2103   </div></div>
2104 <div class="bottomlang">
2105 <p><span>Available Languages: </span><a href="../en/misc/rewriteguide.html" title="English">&nbsp;en&nbsp;</a> |
2106 <a href="../ko/misc/rewriteguide.html" hreflang="ko" rel="alternate" title="Korean">&nbsp;ko&nbsp;</a></p>
2107 </div><div id="footer">
2108 <p class="apache">Copyright 2009 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>
2109 <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>
2110 </body></html>