You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@httpd.apache.org by rb...@apache.org on 2026/04/30 17:17:38 UTC

svn commit: r1933612 - httpd/httpd/branches/2.4.x/docs/manual/rewrite

Author: rbowen
Date: Thu Apr 30 17:17:38 2026
New Revision: 1933612

Log:
rewrite guide: redistribute advanced.xml recipes to topical files (BZ 58892, step 1)

Modified:
   httpd/httpd/branches/2.4.x/docs/manual/rewrite/avoid.xml
   httpd/httpd/branches/2.4.x/docs/manual/rewrite/flags.xml
   httpd/httpd/branches/2.4.x/docs/manual/rewrite/remapping.xml
   httpd/httpd/branches/2.4.x/docs/manual/rewrite/rewritemap.xml

Modified: httpd/httpd/branches/2.4.x/docs/manual/rewrite/avoid.xml
==============================================================================
--- httpd/httpd/branches/2.4.x/docs/manual/rewrite/avoid.xml	Thu Apr 30 17:17:31 2026	(r1933611)
+++ httpd/httpd/branches/2.4.x/docs/manual/rewrite/avoid.xml	Thu Apr 30 17:17:38 2026	(r1933612)
@@ -243,5 +243,60 @@ and in certain other directives.</p>
 
 </section>
 
+<section id="load-balancing">
+
+  <title>Load Balancing</title>
+
+  <dl>
+    <dt>Description:</dt>
+
+    <dd>
+      <p>We wish to distribute load across several back-end
+      servers.</p>
+    </dd>
+
+    <dt>Solution:</dt>
+
+    <dd>
+      <p>Use <module>mod_proxy_balancer</module>, which provides a
+      flexible and featureful load-balancing solution. It supports
+      several balancing algorithms, session stickiness, health checks,
+      and dynamic configuration via the Balancer Manager — none of which
+      are possible with a <module>mod_rewrite</module> approach.</p>
+
+<highlight language="config">
+&lt;Proxy "balancer://mycluster"&gt;
+    BalancerMember "http://one.example.com"
+    BalancerMember "http://two.example.com"
+    BalancerMember "http://three.example.com"
+&lt;/Proxy&gt;
+ProxyPass        "/"  "balancer://mycluster/"
+ProxyPassReverse "/"  "balancer://mycluster/"
+</highlight>
+
+    </dd>
+
+    <dt>Discussion:</dt>
+    <dd>
+
+<p>It is possible to accomplish rudimentary random load balancing using
+<module>mod_rewrite</module> with a <code>rnd</code>
+<directive module="mod_rewrite">RewriteMap</directive>:</p>
+
+<highlight language="config">
+RewriteEngine on
+RewriteMap  lb       "rnd:/path/to/serverlist.txt"
+RewriteRule "^/(.*)" "http://${lb:servers}/$1"     [P,L]
+</highlight>
+
+<p>However, <module>mod_proxy_balancer</module> is far more flexible and
+featureful than anything you can cobble together using
+<module>mod_rewrite</module>, and is the recommended approach.</p>
+
+    </dd>
+  </dl>
+
+</section>
+
 </manualpage>
 

Modified: httpd/httpd/branches/2.4.x/docs/manual/rewrite/flags.xml
==============================================================================
--- httpd/httpd/branches/2.4.x/docs/manual/rewrite/flags.xml	Thu Apr 30 17:17:31 2026	(r1933611)
+++ httpd/httpd/branches/2.4.x/docs/manual/rewrite/flags.xml	Thu Apr 30 17:17:38 2026	(r1933612)
@@ -153,7 +153,7 @@ characters rejected when they are copied
 RewriteRule "^search/(.*)$" "/search.php/$1" "[BCTLS]"
 </highlight>
 
-<p>This flag is available in version 2.4.57 and later.</p>
+<p>This flag is available in version 2.5.1 and later.</p>
 
 </section>
 
@@ -168,7 +168,7 @@ escaped.
 RewriteRule "^search/(.*)$" "/search.php?term=$1" "[B,BNE=/]"
 </highlight>
 
-<p>This flag is available in version 2.4.57 and later.</p>
+<p>This flag is available in version 2.5.1 and later.</p>
 </section>
 
 <section id="flag_c"><title>C|chain</title>
@@ -223,6 +223,7 @@ security model.</dd>
 <dd>A value of 0 indicates that the cookie will persist only for the
 current browser session. This is the default value if none is
 specified.</dd>
+<dd>A negative value causes the cookie to be unset in the browser.</dd>
 
 <dt>Path</dt>
 <dd>The path, on the current website, for which the cookie is valid,
@@ -244,7 +245,7 @@ browsers that support this feature.</dd>
 <dt>samesite</dt>
 <dd>If set to anything other than <code>false</code> or <code>0</code>, the <code>SameSite</code>
 attribute is set to the specified value.  Typical values are <code>None</code>,
-<code>Lax</code>, and <code>Strict</code>. Available in 2.4.47 and later.</dd>
+<code>Lax</code>, and <code>Strict</code>. Available in 2.5.1 and later.</dd>
 </dl>
 
 
@@ -346,6 +347,33 @@ CustomLog   "logs/access_log"    combine
 <p>Note that this same effect can be obtained using <directive
 module="mod_setenvif">SetEnvIf</directive>. This technique is offered as
 an example, not as a recommendation.</p>
+
+<p><strong>Setting environment variables for tracking rewrites</strong></p>
+
+<p>At times, we want to maintain some kind of status when we
+perform a rewrite. For example, you want to make a note that
+you've done that rewrite, so that you can check later to see if a
+request came via that rewrite. One way to do this is by setting an
+environment variable.</p>
+
+<highlight language="config">
+RewriteEngine on
+RewriteRule   "^/horse/(.*)"   "/pony/$1" [E=<strong>rewritten:1</strong>]
+</highlight>
+
+<p>Later in your ruleset you might check for this environment
+variable using a RewriteCond:</p>
+
+<highlight language="config">
+RewriteCond "%{ENV:rewritten}"  =1
+</highlight>
+
+<p>Note that environment variables do not survive an external
+redirect. You might consider using the [CO] flag to set a
+cookie. For per-directory and htaccess rewrites, where the final
+substitution is processed as an internal redirect, environment
+variables from the previous round of rewriting are prefixed with
+"REDIRECT_". </p>
 </section>
 
 <section id="flag_end"><title>END</title>
@@ -495,7 +523,7 @@ pattern still matches (i.e., while the U
 <code>A</code>), perform this substitution (i.e., replace the
 <code>A</code> with a <code>B</code>).</p>
 
-<p>In 2.4.8 and later, this module returns an error after 10,000 iterations to
+<p>In 2.5.0 and later, this module returns an error after 10,000 iterations to
 protect against unintended looping.  An alternative maximum number of
 iterations can be specified by adding to the N flag.  </p>
 <highlight language="config">
@@ -885,14 +913,14 @@ The <code>L</code> flag can be useful in
     This protects from a malicious URL causing the expanded substitution to
     map to an unexpected filesystem location.</p>
 
-    <p><since>2.4.60</since></p>
+    <p><since>2.5.1</since></p>
 </section>
 <section id="flag_unc"><title>UNC</title>
     <p> Setting this flag prevents the merging of multiple leading slashes,
     as used in Windows UNC paths.  The flag is not necessary when the rules
     substitution starts with multiple literal slashes.</p>
 
-    <p><since>2.4.62</since></p>
+    <p><since>2.5.1</since></p>
 </section>
 
 </manualpage>

Modified: httpd/httpd/branches/2.4.x/docs/manual/rewrite/remapping.xml
==============================================================================
--- httpd/httpd/branches/2.4.x/docs/manual/rewrite/remapping.xml	Thu Apr 30 17:17:31 2026	(r1933611)
+++ httpd/httpd/branches/2.4.x/docs/manual/rewrite/remapping.xml	Thu Apr 30 17:17:38 2026	(r1933612)
@@ -227,11 +227,11 @@ RewriteRule    "^foo\.html$"  "foo.cgi"
 #   when and only when document.php exists
 &lt;Directory "/var/www/htdocs"&gt;
     RewriteEngine on
-    RewriteBase "/var/www/htdocs"
+    RewriteBase   "/var/www/htdocs"
 
-    RewriteCond "$1.php" -f
-    RewriteCond "$1.html" !-f
-    RewriteRule "^(.*).html$" "$1.php"
+    RewriteCond   "$1.php"           -f
+    RewriteCond   "$1.html"          !-f
+    RewriteRule   "^(.*).html$"      "$1.php"
 &lt;/Directory&gt;
 </highlight>
     </dd>
@@ -296,7 +296,7 @@ hostname(s).</p>
 
 <p>You can alternatively accomplish this using the
 <directive module="core" type="section">If</directive>
-directive:</p>
+directive: (<strong>2.4 and later</strong>)</p>
 
 <highlight language="config">
 &lt;If "%{HTTP_HOST} != 'www.example.com'"&gt;
@@ -327,7 +327,7 @@ RewriteRule "^/?(.*)"        "http://www
 
 <p>And for a site running on port 80</p>
 <highlight language="config">
-RewriteCond "%{HTTP_HOST}"   "!^www\.example\.com" [NC]
+RewriteCond "%{HTTP_HOST}"   "!^www\.example\.com"       [NC]
 RewriteCond "%{HTTP_HOST}"   "!^$"
 RewriteRule "^/?(.*)"        "http://www.example.com/$1" [L,R,NE]
 </highlight>
@@ -340,7 +340,7 @@ RewriteRule "^/?(.*)"        "http://www
         recipe:</p>
 
 <highlight language="config">
-RewriteCond "%{HTTP_HOST}" "!^www\." [NC]
+RewriteCond "%{HTTP_HOST}" "!^www\."                    [NC]
 RewriteCond "%{HTTP_HOST}" "!^$"
 RewriteRule "^/?(.*)"      "http://www.%{HTTP_HOST}/$1" [L,R,NE]
 </highlight>
@@ -389,7 +389,7 @@ RewriteRule "^(.+)" "%{DOCUMENT_ROOT}/<s
 
 #   else go on for other Alias or ScriptAlias directives,
 #   etc.
-RewriteRule   "^"  "-"  [PT]
+RewriteRule "^"     "-"                                          [PT]
 </highlight>
     </dd>
   </dl>
@@ -422,8 +422,8 @@ RewriteRule   "^"  "-"  [PT]
 HostnameLookups on
 RewriteEngine on
 RewriteMap    multiplex         "txt:/path/to/map.mirrors"
-RewriteCond   "%{REMOTE_HOST}"  "([a-z]+)$" [NC]
-RewriteRule   "^/(.*)$"  "${multiplex:<strong>%1</strong>|http://www.example.com/}$1"  [R,L]
+RewriteCond  "%{REMOTE_HOST}"   "([a-z]+)$"                [NC]
+RewriteRule  "^/(.*)$"          "${multiplex:<strong>%1</strong>|http://www.example.com/}$1"  [R,L]
 </highlight>
 
 <example>
@@ -453,46 +453,6 @@ com       http://www.example.com/<br />
 
 </section>
 
-<section id="browser-dependent-content">
-
-  <title>Browser Dependent Content</title>
-
-  <dl>
-    <dt>Description:</dt>
-
-    <dd>
-      <p>We wish to provide different content based on the browser, or
-      user-agent, which is requesting the content.</p>
-    </dd>
-
-    <dt>Solution:</dt>
-
-    <dd>
-      <p>We have to decide, based on the HTTP header "User-Agent",
-      which content to serve. The following config
-      does the following: If the HTTP header "User-Agent"
-      contains "Mozilla/3", the page <code>foo.html</code>
-      is rewritten to <code>foo.NS.html</code> and the
-      rewriting stops. If the browser is "Lynx" or "Mozilla" of
-      version 1 or 2, the URL becomes <code>foo.20.html</code>.
-      All other browsers receive page <code>foo.32.html</code>.
-      This is done with the following ruleset:</p>
-
-<highlight language="config">
-RewriteCond "%{HTTP_USER_AGENT}"  "^<strong>Mozilla/3</strong>.*"
-RewriteRule "^foo\.html$"         "foo.<strong>NS</strong>.html"          [<strong>L</strong>]
-
-RewriteCond "%{HTTP_USER_AGENT}"  "^Lynx/" [OR]
-RewriteCond "%{HTTP_USER_AGENT}"  "^Mozilla/[12]"
-RewriteRule "^foo\.html$"         "foo.<strong>20</strong>.html"          [<strong>L</strong>]
-
-RewriteRule "^foo\.html$"         "foo.<strong>32</strong>.html"          [<strong>L</strong>]
-</highlight>
-    </dd>
-  </dl>
-
-</section>
-
 <section id="canonicalurl">
 
 <title>Canonical URLs</title>
@@ -530,7 +490,7 @@ RewriteRule   "^/(puppies|canines)/(.*)"
 
      <highlight language="config">
 RedirectMatch "^/(puppies|canines)/(.*)" "/dogs/$2"
-</highlight>
+     </highlight>
      </dd>
       </dl>
 
@@ -600,7 +560,7 @@ module="mod_dir">FallbackResource</direc
 
 <highlight language="config">
 &lt;Directory "/var/www/my_blog"&gt;
-  FallbackResource "index.php"
+  FallbackResource index.php
 &lt;/Directory&gt;
 </highlight>
 
@@ -614,7 +574,7 @@ set to accomplish the same thing:</p>
 
   RewriteCond "/var/www/my_blog/%{REQUEST_FILENAME}" !-f
   RewriteCond "/var/www/my_blog/%{REQUEST_FILENAME}" !-d
-  RewriteRule "^" "index.php" [PT]
+  RewriteRule "^"                                    "index.php" [PT]
 &lt;/Directory&gt;
 </highlight>
 
@@ -656,7 +616,7 @@ substitutions.</p>
 <highlight language="config">
 # Remove mykey=???
 RewriteCond "%{QUERY_STRING}" "(.*(?:^|&amp;))mykey=([^&amp;]*)&amp;?(.*)&amp;?$"
-RewriteRule "(.*)" "$1?%1%3"
+RewriteRule "(.*)"            "$1?%1%3"
 </highlight>
   </li>
 
@@ -666,7 +626,7 @@ RewriteRule "(.*)" "$1?%1%3"
 <highlight language="config">
 # Copy from query string to PATH_INFO
 RewriteCond "%{QUERY_STRING}" "(.*(?:^|&amp;))mykey=([^&amp;]*)&amp;?(.*)&amp;?$"
-RewriteRule "(.*)" "$1/products/%2/?" [PT]
+RewriteRule "(.*)"            "$1/products/%2/?" [PT]
 </highlight>
   </li>
 
@@ -675,8 +635,8 @@ RewriteRule "(.*)" "$1/products/%2/?" [P
 <highlight language="config">
 # Capture the value of mykey in the query string
 RewriteCond "%{QUERY_STRING}" "(.*(?:^|&amp;))mykey=([^&amp;]*)&amp;?(.*)&amp;?$"
-RewriteCond "%2" !=not-so-secret-value 
-RewriteRule "(.*)" - [F]
+RewriteCond "%2"              !=not-so-secret-value
+RewriteRule "(.*)"            "-" [F]
 </highlight>
   </li>
 
@@ -695,5 +655,155 @@ RewriteRule "^/?path/([^/]+)/([^/]+)" "/
 </dl>
 </section>
 
+<section id="structuredhomedirs">
+
+  <title>Structured Userdirs</title>
+
+  <dl>
+    <dt>Description:</dt>
+
+    <dd>
+      <p>Some sites with thousands of users use a
+      structured homedir layout, <em>i.e.</em> each homedir is in a
+      subdirectory which begins (for instance) with the first
+      character of the username. So, <code>/~larry/anypath</code>
+      is <code>/home/<strong>l</strong>/larry/public_html/anypath</code>
+      while <code>/~waldo/anypath</code> is
+      <code>/home/<strong>w</strong>/waldo/public_html/anypath</code>.</p>
+    </dd>
+
+    <dt>Solution:</dt>
+
+    <dd>
+      <p>We use the following ruleset to expand the tilde URLs
+      into the above layout.</p>
+
+<highlight language="config">
+RewriteEngine on
+RewriteRule   "^/~(<strong>([a-z])</strong>[a-z0-9]+)(.*)"  "/home/<strong>$2</strong>/$1/public_html$3"
+</highlight>
+    </dd>
+  </dl>
+
+</section>
+
+<section id="redirectanchors">
+
+  <title>Redirecting Anchors</title>
+
+  <dl>
+    <dt>Description:</dt>
+
+    <dd>
+    <p>By default, redirecting to an HTML anchor doesn't work,
+    because <module>mod_rewrite</module> escapes the <code>#</code> character,
+    turning it into <code>%23</code>. This, in turn, breaks the
+    redirection.</p>
+    </dd>
+
+    <dt>Solution:</dt>
+
+    <dd>
+      <p>Use the <code>[NE]</code> flag on the
+      <code>RewriteRule</code>. NE stands for No Escape.
+      </p>
+    </dd>
+
+    <dt>Discussion:</dt>
+    <dd>This technique will of course also work with other
+    special characters that <module>mod_rewrite</module>, by default, URL-encodes.</dd>
+  </dl>
+
+</section>
+
+<section id="time-dependent">
+
+  <title>Time-Dependent Rewriting</title>
+
+  <dl>
+    <dt>Description:</dt>
+
+    <dd>
+      <p>We wish to use <module>mod_rewrite</module> to serve different content based on
+      the time of day.</p>
+    </dd>
+
+    <dt>Solution:</dt>
+
+    <dd>
+      <p>There are a lot of variables named <code>TIME_xxx</code>
+      for rewrite conditions. In conjunction with the special
+      lexicographic comparison patterns <code>&lt;STRING</code>,
+      <code>&gt;STRING</code> and <code>=STRING</code> we can
+      do time-dependent redirects:</p>
+
+<highlight language="config">
+RewriteEngine on
+RewriteCond   "%{TIME_HOUR}%{TIME_MIN}" &gt;0700
+RewriteCond   "%{TIME_HOUR}%{TIME_MIN}" &lt;1900
+RewriteRule   "^foo\.html$"             "foo.day.html" [L]
+RewriteRule   "^foo\.html$"             "foo.night.html"
+</highlight>
+
+      <p>This provides the content of <code>foo.day.html</code>
+      under the URL <code>foo.html</code> from
+      <code>07:01-18:59</code> and at the remaining time the
+      contents of <code>foo.night.html</code>.</p>
+
+      <note type="warning"><module>mod_cache</module>, intermediate proxies
+      and browsers may each cache responses and cause the either page to be
+      shown outside of the time-window configured.
+      <module>mod_expires</module> may be used to control this
+      effect. You are, of course, much better off simply serving the
+      content dynamically, and customizing it based on the time of day.</note>
+
+    </dd>
+  </dl>
+
+</section>
+
+<section id="on-the-fly-content">
+
+  <title>On-the-fly Content-Regeneration</title>
+
+  <dl>
+    <dt>Description:</dt>
+
+    <dd>
+      <p>We wish to dynamically generate content, but store it
+      statically once it is generated. This rule will check for the
+      existence of the static file, and if it's not there, generate
+      it. The static files can be removed periodically, if desired (say,
+      via cron) and will be regenerated on demand.</p>
+    </dd>
+
+    <dt>Solution:</dt>
+
+    <dd>
+      This is done via the following ruleset:
+
+<highlight language="config">
+# This example is valid in per-directory context only
+RewriteCond "%{REQUEST_URI}"   !-U
+RewriteRule "^(.+)\.html$"     "/regenerate_page.cgi"   [PT,L]
+</highlight>
+
+    <p>The <code>-U</code> operator determines whether the test string
+    (in this case, <code>REQUEST_URI</code>) is a valid URL. It does
+    this via a subrequest. In the event that this subrequest fails -
+    that is, the requested resource doesn't exist - this rule invokes
+    the CGI program <code>/regenerate_page.cgi</code>, which generates
+    the requested resource and saves it into the document directory, so
+    that the next time it is requested, a static copy can be served.</p>
+
+    <p>In this way, documents that are infrequently updated can be served in
+    static form. if documents need to be refreshed, they can be deleted
+    from the document directory, and they will then be regenerated the
+    next time they are requested.</p>
+    </dd>
+  </dl>
+
+</section>
+
 
 </manualpage>

Modified: httpd/httpd/branches/2.4.x/docs/manual/rewrite/rewritemap.xml
==============================================================================
--- httpd/httpd/branches/2.4.x/docs/manual/rewrite/rewritemap.xml	Thu Apr 30 17:17:31 2026	(r1933611)
+++ httpd/httpd/branches/2.4.x/docs/manual/rewrite/rewritemap.xml	Thu Apr 30 17:17:38 2026	(r1933612)
@@ -470,6 +470,65 @@ RewriteMap myquery "fastdbd:SELECT desti
     (such as case-sensitivity) required for your database.</p></note>
 
   </section>
+
+  <section id="sharding">
+
+  <title>URL-based sharding across multiple backends</title>
+
+  <dl>
+    <dt>Description:</dt>
+
+    <dd>
+      <p>A common technique for distributing the burden of
+      server load or storage space is called "sharding".
+      When using this method, a front-end server will use the
+      url to consistently "shard" users or objects to separate
+      backend servers.</p>
+    </dd>
+
+    <dt>Solution:</dt>
+
+    <dd>
+      <p>A mapping is maintained, from users to target servers, in
+      external map files. They look like:</p>
+
+<example>
+user1  physical_host_of_user1<br />
+user2  physical_host_of_user2<br />
+# ... and so on
+</example>
+
+  <p>We put this into a <code>map.users-to-hosts</code> file. The
+    aim is to map;</p>
+
+<example>
+/u/user1/anypath
+</example>
+
+  <p>to</p>
+
+<example>
+http://physical_host_of_user1/u/user/anypath
+</example>
+
+      <p>thus every URL path need not be valid on every backend physical
+      host. The following ruleset does this for us with the help of the map
+      files assuming that server0 is a default server which will be used if
+      a user has no entry in the map:</p>
+
+<highlight language="config">
+RewriteEngine on
+RewriteMap    users-to-hosts      "txt:/path/to/map.users-to-hosts"
+RewriteRule   "^/u/([^/]+)/?(.*)" "http://${users-to-hosts:$1|server0}/u/$1/$2"
+</highlight>
+    </dd>
+  </dl>
+
+  <p>See the <directive module="mod_rewrite">RewriteMap</directive>
+  documentation for more discussion of the syntax of this directive.</p>
+
+  </section>
+
   <section id="summary">
     <title>Summary</title>