1 <?xml version="1.0" encoding="UTF-8" ?>
2 <!DOCTYPE manualpage SYSTEM "../style/manualpage.dtd">
3 <?xml-stylesheet type="text/xsl" href="../style/manual.en.xsl"?>
4 <!-- $LastChangedRevision: 832069 $ -->
7 Licensed to the Apache Software Foundation (ASF) under one or more
8 contributor license agreements. See the NOTICE file distributed with
9 this work for additional information regarding copyright ownership.
10 The ASF licenses this file to You under the Apache License, Version 2.0
11 (the "License"); you may not use this file except in compliance with
12 the License. You may obtain a copy of the License at
14 http://www.apache.org/licenses/LICENSE-2.0
16 Unless required by applicable law or agreed to in writing, software
17 distributed under the License is distributed on an "AS IS" BASIS,
18 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19 See the License for the specific language governing permissions and
20 limitations under the License.
23 <manualpage metafile="remapping.xml.meta">
24 <parentdocument href="./">Rewrite</parentdocument>
26 <title>Redirecting and Remapping with mod_rewrite</title>
30 <p>This document supplements the <module>mod_rewrite</module>
31 <a href="../mod/mod_rewrite.html">reference documentation</a>. It describes
32 how you can use <module>mod_rewrite</module> to redirect and remap
33 request. This includes many examples of common uses of mod_rewrite,
34 including detailed descriptions of how each works.</p>
36 <note type="warning">Note that many of these examples won't work unchanged in your
37 particular server configuration, so it's important that you understand
38 them, rather than merely cutting and pasting the examples into your
42 <seealso><a href="../mod/mod_rewrite.html">Module documentation</a></seealso>
43 <seealso><a href="intro.html">mod_rewrite introduction</a></seealso>
44 <!-- <seealso><a href="remapping.html">Redirection and remapping</a></seealso> -->
45 <seealso><a href="access.html">Controlling access</a></seealso>
46 <seealso><a href="advanced.html">Advanced techniques and tricks</a></seealso>
47 <seealso><a href="avoid.html">When not to use mod_rewrite</a></seealso>
49 <section id="old-to-new">
51 <title>From Old to New (internal)</title>
57 <p>Assume we have recently renamed the page
58 <code>foo.html</code> to <code>bar.html</code> and now want
59 to provide the old URL for backward compatibility. However,
60 we want that users of the old URL even not recognize that
61 the pages was renamed - that is, we don't want the address to
62 change in their browser.</p>
68 <p>We rewrite the old URL to the new one internally via the
73 RewriteRule ^<strong>/old</strong>\.html$ <strong>/new</strong>.html [PT]
80 <section id="old-to-new-extern">
82 <title>Rewriting From Old to New (external)</title>
88 <p>Assume again that we have recently renamed the page
89 <code>foo.html</code> to <code>bar.html</code> and now want
90 to provide the old URL for backward compatibility. But this
91 time we want that the users of the old URL get hinted to
92 the new one, i.e. their browsers Location field should
99 <p>We force a HTTP redirect to the new URL which leads to a
100 change of the browsers and thus the users view:</p>
104 RewriteRule ^<strong>/foo</strong>\.html$ <strong>bar</strong>.html [<strong>R</strong>]
111 <p>In this example, as contrasted to the <a
112 href="#old-to-new-intern">internal</a> example above, we can simply
113 use the Redirect directive. mod_rewrite was used in that earlier
114 example in order to hide the redirect from the client:</p>
117 Redirect /foo.html /bar.html
125 <section id="movehomedirs">
127 <title>Resource Moved to Another Server</title>
130 <dt>Description:</dt>
133 <p>If a resource has moved to another server, you may wish to have
134 URLs continue to work for a time on the old server while people
135 update their bookmarks.</p>
141 <p>You can use <module>mod_rewrite</module> to redirect these URLs
142 to the new server, but you might also consider using the Redirect
143 or RedirectMatch directive.</p>
145 <example><title>With mod_rewrite</title><pre>
147 RewriteRule ^/docs/(.+) http://new.example.com/docs/$1 [R,L]
150 <example><title>With RedirectMatch</title><pre>
151 RedirectMatch ^/docs/(.*) http://new.example.com/docs/$1
154 <example><title>With Redirect</title><pre>
155 Redirect /docs/ http://new.example.com/docs/
162 <section id="static-to-dynamic">
164 <title>From Static to Dynamic</title>
167 <dt>Description:</dt>
170 <p>How can we transform a static page
171 <code>foo.html</code> into a dynamic variant
172 <code>foo.cgi</code> in a seamless way, i.e. without notice
173 by the browser/user.</p>
179 <p>We just rewrite the URL to the CGI-script and force the
180 handler to be <strong>cgi-script</strong> so that it is
181 executed as a CGI program.
182 This way a request to <code>/~quux/foo.html</code>
183 internally leads to the invocation of
184 <code>/~quux/foo.cgi</code>.</p>
189 RewriteRule ^foo\.<strong>html</strong>$ foo.<strong>cgi</strong> [H=<strong>cgi-script</strong>]
196 <section id="backward-compatibility">
198 <title>Backward Compatibility for file extension change</title>
201 <dt>Description:</dt>
204 <p>How can we make URLs backward compatible (still
205 existing virtually) after migrating <code>document.YYYY</code>
206 to <code>document.XXXX</code>, e.g. after translating a
207 bunch of <code>.html</code> files to <code>.php</code>?</p>
213 <p>We rewrite the name to its basename and test for
214 existence of the new extension. If it exists, we take
215 that name, else we rewrite the URL to its original state.</p>
218 # backward compatibility ruleset for
219 # rewriting document.html to document.php
220 # when and only when document.php exists
221 <Directory /var/www/htdocs>
223 RewriteBase /var/www/htdocs
225 RewriteCond $1.php -f
226 RewriteCond $1.html !-f
227 RewriteRule ^(.*).html$ $1.php
234 <p>This example uses an often-overlooked feature of mod_rewrite,
235 by taking advantage of the order of execution of the ruleset. In
236 particular, mod_rewrite evaluates the left-hand-side of the
237 RewriteRule before it evaluates the RewriteCond directives.
238 Consequently, $1 is already defined by the time the RewriteCond
239 directives are evaluated. This allows us to test for the existence
240 of the original (<code>document.html</code>) and target
241 (<code>document.php</code>) files using the same base filename.</p>
243 <p>This ruleset is designed to use in a per-directory context (In a
244 <Directory> block or in a .htaccess file), so that the
245 <code>-f</code> checks are looking at the correct directory path.
246 You may need to set a <directive
247 module="mod_rewite">RewriteBase</directive> directive to specify the
248 directory base that you're working in.</p>
254 <section id="canonicalhost">
256 <title>Canonical Hostnames</title>
259 <dt>Description:</dt>
261 <dd>The goal of this rule is to force the use of a particular
262 hostname, in preference to other hostnames which may be used to
263 reach the same site. For example, if you wish to force the use
264 of <strong>www.example.com</strong> instead of
265 <strong>example.com</strong>, you might use a variant of the
266 following recipe.</dd>
271 <p>For sites running on a port other than 80:</p>
273 RewriteCond %{HTTP_HOST} !^www\.example\.com [NC]
274 RewriteCond %{HTTP_HOST} !^$
275 RewriteCond %{SERVER_PORT} !^80$
276 RewriteRule ^/?(.*) http://www.example.com:%{SERVER_PORT}/$1 [L,R,NE]
279 <p>And for a site running on port 80</p>
281 RewriteCond %{HTTP_HOST} !^www\.example\.com [NC]
282 RewriteCond %{HTTP_HOST} !^$
283 RewriteRule ^/?(.*) http://www.example.com/$1 [L,R,NE]
287 If you wanted to do this generically for all domain names - that
288 is, if you want to redirect <strong>example.com</strong> to
289 <strong>www.example.com</strong> for all possible values of
290 <strong>example.com</strong>, you could use the following
294 RewriteCond %{HTTP_HOST} !^www\. [NC]
295 RewriteCond %{HTTP_HOST} !^$
296 RewriteRule ^/?(.*) http://www.%{HTTP_HOST}/$1 [L,R,NE]
299 <p>These rulesets will work either in your main server configuration
300 file, or in a <code>.htaccess</code> file placed in the <directive
301 module="core">DocumentRoot</directive> of the server.</p>
307 <section id="multipledirs">
309 <title>Search for pages in more than one directory</title>
312 <dt>Description:</dt>
315 <p>A particular resource might exist in one of several places, and
316 we want to look in those places for the resource when it is
317 requested. Perhaps we've recently rearranged our directory
318 structure, dividing content into several locations.</p>
324 <p>The following ruleset searches in two directories to find the
325 resource, and, if not finding it in either place, will attempt to
326 just serve it out of the location requested.</p>
331 # first try to find it in dir1/...
332 # ...and if found stop and be happy:
333 RewriteCond %{DOCUMENT_ROOT}/<strong>dir1</strong>/%{REQUEST_URI} -f
334 RewriteRule ^(.+) %{DOCUMENT_ROOT}/<strong>dir1</strong>/$1 [L]
336 # second try to find it in dir2/...
337 # ...and if found stop and be happy:
338 RewriteCond %{DOCUMENT_ROOT}/<strong>dir2</strong>/%{REQUEST_URI} -f
339 RewriteRule ^(.+) %{DOCUMENT_ROOT}/<strong>dir2</strong>/$1 [L]
341 # else go on for other Alias or ScriptAlias directives,
343 RewriteRule ^(.+) - [PT]
350 <section id="archive-access-multiplexer">
352 <title>Redirecting to Geographically Distributed Servers</title>
355 <dt>Description:</dt>
358 <p>We have numerous mirrors of our website, and want to redirect
359 people to the one that is located in the country where they are
366 <p>Looking at the hostname of the requesting client, we determine
367 which country they are coming from. If we can't do a lookup on their
368 IP address, we fall back to a default server.</p>
369 <p>We'll use a <directive module="mod_rewrite">RewriteMap</directive>
370 directive to build a list of servers that we wish to use.</p>
375 RewriteMap multiplex txt:/path/to/map.mirrors
376 RewriteCond %{REMOTE_HOST} ([a-z]+)$ [NC]
377 RewriteRule ^/(.*)$ ${multiplex:<strong>%1</strong>|http://www.example.com/}$1 [R,L]
381 ## map.mirrors -- Multiplexing Map
383 de http://www.example.de/
384 uk http://www.example.uk/
385 com http://www.example.com/
392 <note type="warning">This ruleset relies on
393 <directive module="core">HostNameLookups</directive>
394 being set <code>on</code>, which can be
395 a significant performance hit.</note>
397 <p>The <directive module="mod_rewrite">RewriteCond</directive>
398 directive captures the last portion of the hostname of the
399 requesting client - the country code - and the following RewriteRule
400 uses that value to look up the appropriate mirror host in the map
407 <section id="browser-dependent-content">
409 <title>Browser Dependent Content</title>
412 <dt>Description:</dt>
415 <p>We wish to provide different content based on the browser, or
416 user-agent, which is requesting the content.</p>
422 <p>We have to decide, based on the HTTP header "User-Agent",
423 which content to serve. The following config
424 does the following: If the HTTP header "User-Agent"
425 contains "Mozilla/3", the page <code>foo.html</code>
426 is rewritten to <code>foo.NS.html</code> and the
427 rewriting stops. If the browser is "Lynx" or "Mozilla" of
428 version 1 or 2, the URL becomes <code>foo.20.html</code>.
429 All other browsers receive page <code>foo.32.html</code>.
430 This is done with the following ruleset:</p>
433 RewriteCond %{HTTP_USER_AGENT} ^<strong>Mozilla/3</strong>.*
434 RewriteRule ^foo\.html$ foo.<strong>NS</strong>.html [<strong>L</strong>]
436 RewriteCond %{HTTP_USER_AGENT} ^<strong>Lynx/</strong>.* [OR]
437 RewriteCond %{HTTP_USER_AGENT} ^<strong>Mozilla/[12]</strong>.*
438 RewriteRule ^foo\.html$ foo.<strong>20</strong>.html [<strong>L</strong>]
440 RewriteRule ^foo\.html$ foo.<strong>32</strong>.html [<strong>L</strong>]
447 <section id="canonicalurl">
449 <title>Canonical URLs</title>
452 <dt>Description:</dt>
455 <p>On some webservers there is more than one URL for a
456 resource. Usually there are canonical URLs (which are be
457 actually used and distributed) and those which are just
458 shortcuts, internal ones, and so on. Independent of which URL the
459 user supplied with the request, they should finally see the
460 canonical one in their browser address bar.</p>
466 <p>We do an external HTTP redirect for all non-canonical
467 URLs to fix them in the location view of the Browser and
468 for all subsequent requests. In the example ruleset below
469 we replace <code>/puppies</code> and <code>/canines</code>
470 by the canonical <code>/dogs</code>.</p>
473 RewriteRule ^/(puppies|canines)/(.*) /dogs/$2 [R]
479 This should really be accomplished with Redirect or RedirectMatch
483 RedirectMatch ^/(puppies|canines)/(.*) /dogs/$2
490 <section id="uservhosts">
492 <title>Virtual Hosts Per User</title>
495 <dt>Description:</dt>
498 <p>We want to automatically create a virtual host for every user who
499 has an account on our web server system, without having to create
500 new VirtualHost sections.</p>
502 <p>In this recipe, we assume that we'll be using the hostname
503 <code>www.<strong>username</strong>.example.com</code> for each
504 user, and serve their content out of
505 <code>/home/<strong>username</strong>/www</code>.</p>
514 RewriteCond %{<strong>HTTP_HOST</strong>} ^www\.<strong>([^.]+)</strong>\.example\.com$
515 RewriteRule ^(.*) /home/<strong>%1</strong>/www$1
516 </pre></example></dd>
521 <note type="warning">You will need to take care of the DNS
522 resolution - Apache does
523 not handle name resolution. You'll need either to create CNAME
524 records for each hostname, or a DNS wildcard record. Creating DNS
525 records is beyond the scope of this document.</note>
527 <p>Parentheses used in a <directive
528 module="mod_rewrite">RewriteCond</directive> are captured into the
529 backreferences <code>%1</code>, <code>%2</code>, etc, while parentheses
530 used in <directive module="mod_rewrite">RewriteRule</directive> are
531 captured into the backreferences <code>$1</code>, <code>$2</code>,
535 As with many techniques discussed in this document, mod_rewrite really
536 isn't the best way to accomplish this task. You should, instead,
537 consider using <module>mod_vhost_alias</module> instead, as it will much
538 more gracefully handle anything beyond serving static files, such as any
539 dynamic content, and Alias resolution.
546 <section id="moveddocroot">
548 <title>Moved <code>DocumentRoot</code></title>
551 <dt>Description:</dt>
554 <p>Usually the <directive module="core">DocumentRoot</directive>
555 of the webserver directly relates to the URL "<code>/</code>".
556 But often this data is not really of top-level priority. For example,
557 you may wish for visitors, on first entering a site, to go to a
558 particular subdirectory <code>/about/</code>. This may be accomplished
559 using the following ruleset:</p>
565 <p>We redirect the URL <code>/</code> to
566 <code>/about/</code>:
571 RewriteRule <strong>^/$</strong> /about/ [<strong>R</strong>]
574 <p>Note that this can also be handled using the <directive
575 module="mod_alias">RedirectMatch</directive> directive:</p>
578 RedirectMatch ^/$ http://example.com/about/
581 <p>Note also that the example rewrites only the root URL. That is, it
582 rewrites a request for <code>http://example.com/</code>, but not a
583 request for <code>http://example.com/page.html</code>. If you have in
584 fact changed your document root - that is, if <strong>all</strong> of
585 your content is in fact in that subdirectory, it is greatly preferable
586 to simply change your <directive module="core">DocumentRoot</directive>
587 directive, or move all of the content up one directory,
588 rather than rewriting URLs.</p>
594 <section id="fallback-resource">
595 <title>Fallback Resource</title>
598 <dt>Description:</dt>
599 <dd>You want a single resource (say, a certain file, like index.php) to
600 handle all requests that come to a particular directory, except those
601 that should go to an existing resource such as an image, or a css file.</dd>
605 <p>As of version 2.4, you should use the <directive
606 module="mod_dir">FallbackResource</directive> directive for this:</p>
610 <Directory /var/www/my_blog>
611 FallbackResource index.php
616 <p>However, in earlier versions of Apache, or if your needs are more
617 complicated than this, you can use a variation of the following rewrite
618 set to accomplish the same thing:</p>
622 <Directory /var/www/my_blog>
625 RewriteCond /var/www/my_blog/%{REQUEST_FILENAME} !-f
626 RewriteCond /var/www/my_blog/%{REQUEST_FILENAME} !-d
627 RewriteRule ^ index.php [PT]
632 <p>If, on the other hand, you wish to pass the requested URI as a query
633 string argument to index.php, you can replace that RewriteRule with:</p>
637 RewriteRule (.*) index.php?$1 [PT,QSA]
641 <p>Note that these rulesets can be uses in a <code>.htaccess</code>
642 file, as well as in a <Directory> block.</p>
650 <section id="mass-virtual-hosting">
652 <title>Mass Virtual Hosting</title>
655 <dt>Description:</dt>
658 <p>Mass virtual hosting is one of the more common uses of
659 mod_rewrite. However, it is seldom the best way to handle mass
660 virtual hosting. This topic is discussed at great length in the <a
661 href="../vhosts/mass.html">virtual host documentation</a>.</p>
667 <section id="dynamic-proxy">
669 <title>Proxying Content with mod_rewrite</title>
672 <dt>Description:</dt>
676 mod_rewrite provides the [P] flag, which allows URLs to be passed,
677 via mod_proxy, to another server. Two examples are given here. In
678 one example, a URL is passed directly to another server, and served
679 as though it were a local URL. In the other example, we proxy
680 missing content to a back-end server.</p>
686 <p>To simply map a URL to another server, we use the [P] flag, as
691 RewriteBase /products/
692 RewriteRule ^<strong>widget/</strong>(.*)$ <strong>http://product.example.com/widget/</strong>$1 [<strong>P</strong>]
693 ProxyPassReverse /products/widget/ http://product.example.com/widget/
696 <p>In the second example, we proxy the request only if we can't find
697 the resource locally. This can be very useful when you're migrating
698 from one server to another, and you're not sure if all the content
699 has been migrated yet.</p>
702 RewriteCond %{REQUEST_FILENAME} <strong>!-f</strong>
703 RewriteCond %{REQUEST_FILENAME} <strong>!-d</strong>
704 RewriteRule ^/(.*) http://<strong>old</strong>.example.com$1 [<strong>P</strong>]
705 ProxyPassReverse / http://old.example.com/
711 <dd><p>In each case, we add a <directive
712 module="mod_proxy">ProxyPassReverse</directive> directive to ensure
713 that any redirects issued by the backend are correctly passed on to
716 <p>Consider using either <directive
717 module="mod_proxy">ProxyPass</directive> or <directive
718 module="mod_rewrite">ProxyPassMatch</directive> whenever possible in
719 preference to mod_rewrite.</p>