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$ -->
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="vhosts.html">Virtual hosts</a></seealso>
47 <seealso><a href="proxy.html">Proxying</a></seealso>
48 <seealso><a href="advanced.html">Advanced techniques and tricks</a></seealso>
49 <seealso><a href="avoid.html">When not to use mod_rewrite</a></seealso>
51 <section id="old-to-new">
53 <title>From Old to New (internal)</title>
59 <p>Assume we have recently renamed the page
60 <code>foo.html</code> to <code>bar.html</code> and now want
61 to provide the old URL for backward compatibility. However,
62 we want that users of the old URL even not recognize that
63 the pages was renamed - that is, we don't want the address to
64 change in their browser.</p>
70 <p>We rewrite the old URL to the new one internally via the
75 RewriteRule ^<strong>/old</strong>\.html$ <strong>/new</strong>.html [PT]
82 <section id="old-to-new-extern">
84 <title>Rewriting From Old to New (external)</title>
90 <p>Assume again that we have recently renamed the page
91 <code>foo.html</code> to <code>bar.html</code> and now want
92 to provide the old URL for backward compatibility. But this
93 time we want that the users of the old URL get hinted to
94 the new one, i.e. their browsers Location field should
101 <p>We force a HTTP redirect to the new URL which leads to a
102 change of the browsers and thus the users view:</p>
106 RewriteRule ^<strong>/foo</strong>\.html$ <strong>bar</strong>.html [<strong>R</strong>]
113 <p>In this example, as contrasted to the <a
114 href="#old-to-new-intern">internal</a> example above, we can simply
115 use the Redirect directive. mod_rewrite was used in that earlier
116 example in order to hide the redirect from the client:</p>
119 Redirect /foo.html /bar.html
127 <section id="movehomedirs">
129 <title>Resource Moved to Another Server</title>
132 <dt>Description:</dt>
135 <p>If a resource has moved to another server, you may wish to have
136 URLs continue to work for a time on the old server while people
137 update their bookmarks.</p>
143 <p>You can use <module>mod_rewrite</module> to redirect these URLs
144 to the new server, but you might also consider using the Redirect
145 or RedirectMatch directive.</p>
147 <example><title>With mod_rewrite</title><pre>
149 RewriteRule ^/docs/(.+) http://new.example.com/docs/$1 [R,L]
152 <example><title>With RedirectMatch</title><pre>
153 RedirectMatch ^/docs/(.*) http://new.example.com/docs/$1
156 <example><title>With Redirect</title><pre>
157 Redirect /docs/ http://new.example.com/docs/
164 <section id="static-to-dynamic">
166 <title>From Static to Dynamic</title>
169 <dt>Description:</dt>
172 <p>How can we transform a static page
173 <code>foo.html</code> into a dynamic variant
174 <code>foo.cgi</code> in a seamless way, i.e. without notice
175 by the browser/user.</p>
181 <p>We just rewrite the URL to the CGI-script and force the
182 handler to be <strong>cgi-script</strong> so that it is
183 executed as a CGI program.
184 This way a request to <code>/~quux/foo.html</code>
185 internally leads to the invocation of
186 <code>/~quux/foo.cgi</code>.</p>
191 RewriteRule ^foo\.<strong>html</strong>$ foo.<strong>cgi</strong> [H=<strong>cgi-script</strong>]
198 <section id="backward-compatibility">
200 <title>Backward Compatibility for file extension change</title>
203 <dt>Description:</dt>
206 <p>How can we make URLs backward compatible (still
207 existing virtually) after migrating <code>document.YYYY</code>
208 to <code>document.XXXX</code>, e.g. after translating a
209 bunch of <code>.html</code> files to <code>.php</code>?</p>
215 <p>We rewrite the name to its basename and test for
216 existence of the new extension. If it exists, we take
217 that name, else we rewrite the URL to its original state.</p>
220 # backward compatibility ruleset for
221 # rewriting document.html to document.php
222 # when and only when document.php exists
223 <Directory /var/www/htdocs>
225 RewriteBase /var/www/htdocs
227 RewriteCond $1.php -f
228 RewriteCond $1.html !-f
229 RewriteRule ^(.*).html$ $1.php
236 <p>This example uses an often-overlooked feature of mod_rewrite,
237 by taking advantage of the order of execution of the ruleset. In
238 particular, mod_rewrite evaluates the left-hand-side of the
239 RewriteRule before it evaluates the RewriteCond directives.
240 Consequently, $1 is already defined by the time the RewriteCond
241 directives are evaluated. This allows us to test for the existence
242 of the original (<code>document.html</code>) and target
243 (<code>document.php</code>) files using the same base filename.</p>
245 <p>This ruleset is designed to use in a per-directory context (In a
246 <Directory> block or in a .htaccess file), so that the
247 <code>-f</code> checks are looking at the correct directory path.
248 You may need to set a <directive
249 module="mod_rewite">RewriteBase</directive> directive to specify the
250 directory base that you're working in.</p>
256 <section id="canonicalhost">
258 <title>Canonical Hostnames</title>
261 <dt>Description:</dt>
263 <dd>The goal of this rule is to force the use of a particular
264 hostname, in preference to other hostnames which may be used to
265 reach the same site. For example, if you wish to force the use
266 of <strong>www.example.com</strong> instead of
267 <strong>example.com</strong>, you might use a variant of the
268 following recipe.</dd>
274 <p>The very best way to solve this doesn't involve mod_rewrite at all,
275 but rather uses the <directive module="alias">Redirect</directive>
276 directive places in a virtual host for the non-canonical
280 <VirtualHost *:80>
281 ServerName undesired.example.com
282 ServerAlias example.com notthis.example.com
284 Redirect / http://www.example.com/
288 <p>However, there are situations where you'll need to use mod_rewrite -
289 primarily when you don't have access to the main server configuration
290 file, or if you wish to do this dynamically for a larger number of
291 hostnames. For these situations, you might use one of the recipes
294 <p>For sites running on a port other than 80:</p>
296 RewriteCond %{HTTP_HOST} !^www\.example\.com [NC]
297 RewriteCond %{HTTP_HOST} !^$
298 RewriteCond %{SERVER_PORT} !^80$
299 RewriteRule ^/?(.*) http://www.example.com:%{SERVER_PORT}/$1 [L,R,NE]
302 <p>And for a site running on port 80</p>
304 RewriteCond %{HTTP_HOST} !^www\.example\.com [NC]
305 RewriteCond %{HTTP_HOST} !^$
306 RewriteRule ^/?(.*) http://www.example.com/$1 [L,R,NE]
310 If you wanted to do this generically for all domain names - that
311 is, if you want to redirect <strong>example.com</strong> to
312 <strong>www.example.com</strong> for all possible values of
313 <strong>example.com</strong>, you could use the following
317 RewriteCond %{HTTP_HOST} !^www\. [NC]
318 RewriteCond %{HTTP_HOST} !^$
319 RewriteRule ^/?(.*) http://www.%{HTTP_HOST}/$1 [L,R,NE]
322 <p>These rulesets will work either in your main server configuration
323 file, or in a <code>.htaccess</code> file placed in the <directive
324 module="core">DocumentRoot</directive> of the server.</p>
330 <section id="multipledirs">
332 <title>Search for pages in more than one directory</title>
335 <dt>Description:</dt>
338 <p>A particular resource might exist in one of several places, and
339 we want to look in those places for the resource when it is
340 requested. Perhaps we've recently rearranged our directory
341 structure, dividing content into several locations.</p>
347 <p>The following ruleset searches in two directories to find the
348 resource, and, if not finding it in either place, will attempt to
349 just serve it out of the location requested.</p>
354 # first try to find it in dir1/...
355 # ...and if found stop and be happy:
356 RewriteCond %{DOCUMENT_ROOT}/<strong>dir1</strong>/%{REQUEST_URI} -f
357 RewriteRule ^(.+) %{DOCUMENT_ROOT}/<strong>dir1</strong>/$1 [L]
359 # second try to find it in dir2/...
360 # ...and if found stop and be happy:
361 RewriteCond %{DOCUMENT_ROOT}/<strong>dir2</strong>/%{REQUEST_URI} -f
362 RewriteRule ^(.+) %{DOCUMENT_ROOT}/<strong>dir2</strong>/$1 [L]
364 # else go on for other Alias or ScriptAlias directives,
373 <section id="archive-access-multiplexer">
375 <title>Redirecting to Geographically Distributed Servers</title>
378 <dt>Description:</dt>
381 <p>We have numerous mirrors of our website, and want to redirect
382 people to the one that is located in the country where they are
389 <p>Looking at the hostname of the requesting client, we determine
390 which country they are coming from. If we can't do a lookup on their
391 IP address, we fall back to a default server.</p>
392 <p>We'll use a <directive module="mod_rewrite">RewriteMap</directive>
393 directive to build a list of servers that we wish to use.</p>
398 RewriteMap multiplex txt:/path/to/map.mirrors
399 RewriteCond %{REMOTE_HOST} ([a-z]+)$ [NC]
400 RewriteRule ^/(.*)$ ${multiplex:<strong>%1</strong>|http://www.example.com/}$1 [R,L]
404 ## map.mirrors -- Multiplexing Map
406 de http://www.example.de/
407 uk http://www.example.uk/
408 com http://www.example.com/
415 <note type="warning">This ruleset relies on
416 <directive module="core">HostNameLookups</directive>
417 being set <code>on</code>, which can be
418 a significant performance hit.</note>
420 <p>The <directive module="mod_rewrite">RewriteCond</directive>
421 directive captures the last portion of the hostname of the
422 requesting client - the country code - and the following RewriteRule
423 uses that value to look up the appropriate mirror host in the map
430 <section id="browser-dependent-content">
432 <title>Browser Dependent Content</title>
435 <dt>Description:</dt>
438 <p>We wish to provide different content based on the browser, or
439 user-agent, which is requesting the content.</p>
445 <p>We have to decide, based on the HTTP header "User-Agent",
446 which content to serve. The following config
447 does the following: If the HTTP header "User-Agent"
448 contains "Mozilla/3", the page <code>foo.html</code>
449 is rewritten to <code>foo.NS.html</code> and the
450 rewriting stops. If the browser is "Lynx" or "Mozilla" of
451 version 1 or 2, the URL becomes <code>foo.20.html</code>.
452 All other browsers receive page <code>foo.32.html</code>.
453 This is done with the following ruleset:</p>
456 RewriteCond %{HTTP_USER_AGENT} ^<strong>Mozilla/3</strong>.*
457 RewriteRule ^foo\.html$ foo.<strong>NS</strong>.html [<strong>L</strong>]
459 RewriteCond %{HTTP_USER_AGENT} ^<strong>Lynx/</strong>.* [OR]
460 RewriteCond %{HTTP_USER_AGENT} ^<strong>Mozilla/[12]</strong>.*
461 RewriteRule ^foo\.html$ foo.<strong>20</strong>.html [<strong>L</strong>]
463 RewriteRule ^foo\.html$ foo.<strong>32</strong>.html [<strong>L</strong>]
470 <section id="canonicalurl">
472 <title>Canonical URLs</title>
475 <dt>Description:</dt>
478 <p>On some webservers there is more than one URL for a
479 resource. Usually there are canonical URLs (which are be
480 actually used and distributed) and those which are just
481 shortcuts, internal ones, and so on. Independent of which URL the
482 user supplied with the request, they should finally see the
483 canonical one in their browser address bar.</p>
489 <p>We do an external HTTP redirect for all non-canonical
490 URLs to fix them in the location view of the Browser and
491 for all subsequent requests. In the example ruleset below
492 we replace <code>/puppies</code> and <code>/canines</code>
493 by the canonical <code>/dogs</code>.</p>
496 RewriteRule ^/(puppies|canines)/(.*) /dogs/$2 [R]
502 This should really be accomplished with Redirect or RedirectMatch
506 RedirectMatch ^/(puppies|canines)/(.*) /dogs/$2
513 <section id="moveddocroot">
515 <title>Moved <code>DocumentRoot</code></title>
518 <dt>Description:</dt>
521 <p>Usually the <directive module="core">DocumentRoot</directive>
522 of the webserver directly relates to the URL "<code>/</code>".
523 But often this data is not really of top-level priority. For example,
524 you may wish for visitors, on first entering a site, to go to a
525 particular subdirectory <code>/about/</code>. This may be accomplished
526 using the following ruleset:</p>
532 <p>We redirect the URL <code>/</code> to
533 <code>/about/</code>:
538 RewriteRule <strong>^/$</strong> /about/ [<strong>R</strong>]
541 <p>Note that this can also be handled using the <directive
542 module="mod_alias">RedirectMatch</directive> directive:</p>
545 RedirectMatch ^/$ http://example.com/about/
548 <p>Note also that the example rewrites only the root URL. That is, it
549 rewrites a request for <code>http://example.com/</code>, but not a
550 request for <code>http://example.com/page.html</code>. If you have in
551 fact changed your document root - that is, if <strong>all</strong> of
552 your content is in fact in that subdirectory, it is greatly preferable
553 to simply change your <directive module="core">DocumentRoot</directive>
554 directive, or move all of the content up one directory,
555 rather than rewriting URLs.</p>
561 <section id="fallback-resource">
562 <title>Fallback Resource</title>
565 <dt>Description:</dt>
566 <dd>You want a single resource (say, a certain file, like index.php) to
567 handle all requests that come to a particular directory, except those
568 that should go to an existing resource such as an image, or a css file.</dd>
572 <p>As of version 2.4, you should use the <directive
573 module="mod_dir">FallbackResource</directive> directive for this:</p>
577 <Directory /var/www/my_blog>
578 FallbackResource index.php
583 <p>However, in earlier versions of Apache, or if your needs are more
584 complicated than this, you can use a variation of the following rewrite
585 set to accomplish the same thing:</p>
589 <Directory /var/www/my_blog>
592 RewriteCond /var/www/my_blog/%{REQUEST_FILENAME} !-f
593 RewriteCond /var/www/my_blog/%{REQUEST_FILENAME} !-d
594 RewriteRule ^ index.php [PT]
599 <p>If, on the other hand, you wish to pass the requested URI as a query
600 string argument to index.php, you can replace that RewriteRule with:</p>
604 RewriteRule (.*) index.php?$1 [PT,QSA]
608 <p>Note that these rulesets can be uses in a <code>.htaccess</code>
609 file, as well as in a <Directory> block.</p>