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