|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"><head>
|
|
Packit |
90a5c9 |
<meta content="text/html; charset=ISO-8859-1" http-equiv="Content-Type" />
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
|
Packit |
90a5c9 |
This file is generated from xml source: DO NOT EDIT
|
|
Packit |
90a5c9 |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
|
Packit |
90a5c9 |
-->
|
|
Packit |
90a5c9 |
<title>Redirecting and Remapping with mod_rewrite - Apache HTTP Server Version 2.4</title>
|
|
Packit |
90a5c9 |
<link href="../style/css/manual.css" rel="stylesheet" media="all" type="text/css" title="Main stylesheet" />
|
|
Packit |
90a5c9 |
<link href="../style/css/manual-loose-100pc.css" rel="alternate stylesheet" media="all" type="text/css" title="No Sidebar - Default font size" />
|
|
Packit |
90a5c9 |
<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" />
|
|
Packit |
90a5c9 |
<script src="../style/scripts/prettify.min.js" type="text/javascript">
|
|
Packit |
90a5c9 |
</script>
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
<link href="../images/favicon.ico" rel="shortcut icon" /></head>
|
|
Packit |
90a5c9 |
<body id="manual-page">
|
|
Packit |
90a5c9 |
Modules | Directives | FAQ | Glossary | Sitemap
|
|
Packit |
90a5c9 |
Apache HTTP Server Version 2.4
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
Apache > HTTP Server > Documentation > Version 2.4 > RewriteRedirecting and Remapping with mod_rewrite
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
Available Languages: en |
|
|
Packit |
90a5c9 |
fr
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
This document supplements the mod_rewrite
|
|
Packit |
90a5c9 |
reference documentation. It describes
|
|
Packit |
90a5c9 |
how you can use mod_rewrite to redirect and remap
|
|
Packit |
90a5c9 |
request. This includes many examples of common uses of mod_rewrite,
|
|
Packit |
90a5c9 |
including detailed descriptions of how each works.
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
Note that many of these examples won't work unchanged in your
|
|
Packit |
90a5c9 |
particular server configuration, so it's important that you understand
|
|
Packit |
90a5c9 |
them, rather than merely cutting and pasting the examples into your
|
|
Packit |
90a5c9 |
configuration.
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
Rewriting From Old to New (external)
|
|
Packit |
90a5c9 |
Resource Moved to Another Server
|
|
Packit |
90a5c9 |
From Static to Dynamic
|
|
Packit |
90a5c9 |
Backward Compatibility for file extension change
|
|
Packit |
90a5c9 |
Canonical Hostnames
|
|
Packit |
90a5c9 |
Search for pages in more than one directory
|
|
Packit |
90a5c9 |
Redirecting to Geographically Distributed Servers
|
|
Packit |
90a5c9 |
Browser Dependent Content
|
|
Packit |
90a5c9 |
Canonical URLs
|
|
Packit |
90a5c9 |
Moved DocumentRoot
|
|
Packit |
90a5c9 |
Fallback Resource
|
|
Packit |
90a5c9 |
Rewrite query string
|
|
Packit |
90a5c9 |
See also
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
Description:
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
Assume we have recently renamed the page
|
|
Packit |
90a5c9 |
foo.html to bar.html and now want
|
|
Packit |
90a5c9 |
to provide the old URL for backward compatibility. However,
|
|
Packit |
90a5c9 |
we want that users of the old URL even not recognize that
|
|
Packit |
90a5c9 |
the pages was renamed - that is, we don't want the address to
|
|
Packit |
90a5c9 |
change in their browser.
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
Solution:
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
We rewrite the old URL to the new one internally via the
|
|
Packit |
90a5c9 |
following rule:
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
RewriteEngine on
|
|
Packit |
90a5c9 |
RewriteRule "^/foo\.html$" "/bar.html" [PT]
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
Description:
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
Assume again that we have recently renamed the page
|
|
Packit |
90a5c9 |
foo.html to bar.html and now want
|
|
Packit |
90a5c9 |
to provide the old URL for backward compatibility. But this
|
|
Packit |
90a5c9 |
time we want that the users of the old URL get hinted to
|
|
Packit |
90a5c9 |
the new one, i.e. their browsers Location field should
|
|
Packit |
90a5c9 |
change, too.
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
Solution:
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
We force a HTTP redirect to the new URL which leads to a
|
|
Packit |
90a5c9 |
change of the browsers and thus the users view:
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
RewriteEngine on
|
|
Packit |
90a5c9 |
RewriteRule "^/foo\.html$" "bar.html" [R]
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
Discussion
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
In this example, as contrasted to the internal example above, we can simply
|
|
Packit |
90a5c9 |
use the Redirect directive. mod_rewrite was used in that earlier
|
|
Packit |
90a5c9 |
example in order to hide the redirect from the client:
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
Redirect "/foo.html" "/bar.html"
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
Description:
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
If a resource has moved to another server, you may wish to have
|
|
Packit |
90a5c9 |
URLs continue to work for a time on the old server while people
|
|
Packit |
90a5c9 |
update their bookmarks.
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
Solution:
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
You can use mod_rewrite to redirect these URLs
|
|
Packit |
90a5c9 |
to the new server, but you might also consider using the Redirect
|
|
Packit |
90a5c9 |
or RedirectMatch directive.
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
#With mod_rewrite
|
|
Packit |
90a5c9 |
RewriteEngine on
|
|
Packit |
90a5c9 |
RewriteRule "^/docs/(.+)" "http://new.example.com/docs/$1" [R,L]
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
#With RedirectMatch
|
|
Packit |
90a5c9 |
RedirectMatch "^/docs/(.*)" "http://new.example.com/docs/$1"
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
#With Redirect
|
|
Packit |
90a5c9 |
Redirect "/docs/" "http://new.example.com/docs/"
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
Description:
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
How can we transform a static page
|
|
Packit |
90a5c9 |
foo.html into a dynamic variant
|
|
Packit |
90a5c9 |
foo.cgi in a seamless way, i.e. without notice
|
|
Packit |
90a5c9 |
by the browser/user.
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
Solution:
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
We just rewrite the URL to the CGI-script and force the
|
|
Packit |
90a5c9 |
handler to be cgi-script so that it is
|
|
Packit |
90a5c9 |
executed as a CGI program.
|
|
Packit |
90a5c9 |
This way a request to /~quux/foo.html
|
|
Packit |
90a5c9 |
internally leads to the invocation of
|
|
Packit |
90a5c9 |
/~quux/foo.cgi .
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
RewriteEngine on
|
|
Packit |
90a5c9 |
RewriteBase "/~quux/"
|
|
Packit |
90a5c9 |
RewriteRule "^foo\.html$" "foo.cgi" [H=cgi-script]
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
Description:
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
How can we make URLs backward compatible (still
|
|
Packit |
90a5c9 |
existing virtually) after migrating document.YYYY
|
|
Packit |
90a5c9 |
to document.XXXX , e.g. after translating a
|
|
Packit |
90a5c9 |
bunch of .html files to .php ?
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
Solution:
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
We rewrite the name to its basename and test for
|
|
Packit |
90a5c9 |
existence of the new extension. If it exists, we take
|
|
Packit |
90a5c9 |
that name, else we rewrite the URL to its original state.
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
# backward compatibility ruleset for
|
|
Packit |
90a5c9 |
# rewriting document.html to document.php
|
|
Packit |
90a5c9 |
# when and only when document.php exists
|
|
Packit |
90a5c9 |
<Directory "/var/www/htdocs">
|
|
Packit |
90a5c9 |
RewriteEngine on
|
|
Packit |
90a5c9 |
RewriteBase "/var/www/htdocs"
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
RewriteCond "$1.php" -f
|
|
Packit |
90a5c9 |
RewriteCond "$1.html" !-f
|
|
Packit |
90a5c9 |
RewriteRule "^(.*).html$" "$1.php"
|
|
Packit |
90a5c9 |
</Directory>
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
Discussion
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
This example uses an often-overlooked feature of mod_rewrite,
|
|
Packit |
90a5c9 |
by taking advantage of the order of execution of the ruleset. In
|
|
Packit |
90a5c9 |
particular, mod_rewrite evaluates the left-hand-side of the
|
|
Packit |
90a5c9 |
RewriteRule before it evaluates the RewriteCond directives.
|
|
Packit |
90a5c9 |
Consequently, $1 is already defined by the time the RewriteCond
|
|
Packit |
90a5c9 |
directives are evaluated. This allows us to test for the existence
|
|
Packit |
90a5c9 |
of the original (document.html ) and target
|
|
Packit |
90a5c9 |
(document.php ) files using the same base filename.
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
This ruleset is designed to use in a per-directory context (In a
|
|
Packit |
90a5c9 |
<Directory> block or in a .htaccess file), so that the
|
|
Packit |
90a5c9 |
-f checks are looking at the correct directory path.
|
|
Packit |
90a5c9 |
You may need to set a RewriteBase directive to specify the
|
|
Packit |
90a5c9 |
directory base that you're working in.
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
Description:
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
The goal of this rule is to force the use of a particular
|
|
Packit |
90a5c9 |
hostname, in preference to other hostnames which may be used to
|
|
Packit |
90a5c9 |
reach the same site. For example, if you wish to force the use
|
|
Packit |
90a5c9 |
of www.example.com instead of
|
|
Packit |
90a5c9 |
example.com, you might use a variant of the
|
|
Packit |
90a5c9 |
following recipe.
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
Solution:
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
The very best way to solve this doesn't involve mod_rewrite at all,
|
|
Packit |
90a5c9 |
but rather uses the Redirect
|
|
Packit |
90a5c9 |
directive placed in a virtual host for the non-canonical
|
|
Packit |
90a5c9 |
hostname(s).
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
<VirtualHost *:80>
|
|
Packit |
90a5c9 |
ServerName undesired.example.com
|
|
Packit |
90a5c9 |
ServerAlias example.com notthis.example.com
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
Redirect "/" "http://www.example.com/"
|
|
Packit |
90a5c9 |
</VirtualHost>
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
<VirtualHost *:80>
|
|
Packit |
90a5c9 |
ServerName www.example.com
|
|
Packit |
90a5c9 |
</VirtualHost>
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
You can alternatively accomplish this using the
|
|
Packit |
90a5c9 |
<If>
|
|
Packit |
90a5c9 |
directive:
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
<If "%{HTTP_HOST} != 'www.example.com'">
|
|
Packit |
90a5c9 |
Redirect "/" "http://www.example.com/"
|
|
Packit |
90a5c9 |
</If>
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
Or, for example, to redirect a portion of your site to HTTPS, you
|
|
Packit |
90a5c9 |
might do the following:
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
<If "%{SERVER_PROTOCOL} != 'HTTPS'">
|
|
Packit |
90a5c9 |
Redirect "/admin/" "https://www.example.com/admin/"
|
|
Packit |
90a5c9 |
</If>
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
If, for whatever reason, you still want to use mod_rewrite
|
|
Packit |
90a5c9 |
- if, for example, you need this to work with a larger set of RewriteRules -
|
|
Packit |
90a5c9 |
you might use one of the recipes below.
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
For sites running on a port other than 80:
|
|
Packit |
90a5c9 |
RewriteCond "%{HTTP_HOST}" "!^www\.example\.com" [NC]
|
|
Packit |
90a5c9 |
RewriteCond "%{HTTP_HOST}" "!^$"
|
|
Packit |
90a5c9 |
RewriteCond "%{SERVER_PORT}" "!^80$"
|
|
Packit |
90a5c9 |
RewriteRule "^/?(.*)" "http://www.example.com:%{SERVER_PORT}/$1" [L,R,NE]
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
And for a site running on port 80
|
|
Packit |
90a5c9 |
RewriteCond "%{HTTP_HOST}" "!^www\.example\.com" [NC]
|
|
Packit |
90a5c9 |
RewriteCond "%{HTTP_HOST}" "!^$"
|
|
Packit |
90a5c9 |
RewriteRule "^/?(.*)" "http://www.example.com/$1" [L,R,NE]
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
If you wanted to do this generically for all domain names - that
|
|
Packit |
90a5c9 |
is, if you want to redirect example.com to
|
|
Packit |
90a5c9 |
www.example.com for all possible values of
|
|
Packit |
90a5c9 |
example.com, you could use the following
|
|
Packit |
90a5c9 |
recipe:
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
RewriteCond "%{HTTP_HOST}" "!^www\." [NC]
|
|
Packit |
90a5c9 |
RewriteCond "%{HTTP_HOST}" "!^$"
|
|
Packit |
90a5c9 |
RewriteRule "^/?(.*)" "http://www.%{HTTP_HOST}/$1" [L,R,NE]
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
These rulesets will work either in your main server configuration
|
|
Packit |
90a5c9 |
file, or in a .htaccess file placed in the DocumentRoot of the server.
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
Description:
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
A particular resource might exist in one of several places, and
|
|
Packit |
90a5c9 |
we want to look in those places for the resource when it is
|
|
Packit |
90a5c9 |
requested. Perhaps we've recently rearranged our directory
|
|
Packit |
90a5c9 |
structure, dividing content into several locations.
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
Solution:
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
The following ruleset searches in two directories to find the
|
|
Packit |
90a5c9 |
resource, and, if not finding it in either place, will attempt to
|
|
Packit |
90a5c9 |
just serve it out of the location requested.
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
RewriteEngine on
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
# first try to find it in dir1/...
|
|
Packit |
90a5c9 |
# ...and if found stop and be happy:
|
|
Packit |
90a5c9 |
RewriteCond "%{DOCUMENT_ROOT}/dir1/%{REQUEST_URI}" -f
|
|
Packit |
90a5c9 |
RewriteRule "^(.+)" "%{DOCUMENT_ROOT}/dir1/$1" [L]
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
# second try to find it in dir2/...
|
|
Packit |
90a5c9 |
# ...and if found stop and be happy:
|
|
Packit |
90a5c9 |
RewriteCond "%{DOCUMENT_ROOT}/dir2/%{REQUEST_URI}" -f
|
|
Packit |
90a5c9 |
RewriteRule "^(.+)" "%{DOCUMENT_ROOT}/dir2/$1" [L]
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
# else go on for other Alias or ScriptAlias directives,
|
|
Packit |
90a5c9 |
# etc.
|
|
Packit |
90a5c9 |
RewriteRule "^" "-" [PT]
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
Description:
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
We have numerous mirrors of our website, and want to redirect
|
|
Packit |
90a5c9 |
people to the one that is located in the country where they are
|
|
Packit |
90a5c9 |
located.
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
Solution:
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
Looking at the hostname of the requesting client, we determine
|
|
Packit |
90a5c9 |
which country they are coming from. If we can't do a lookup on their
|
|
Packit |
90a5c9 |
IP address, we fall back to a default server.
|
|
Packit |
90a5c9 |
We'll use a RewriteMap
|
|
Packit |
90a5c9 |
directive to build a list of servers that we wish to use.
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
HostnameLookups on
|
|
Packit |
90a5c9 |
RewriteEngine on
|
|
Packit |
90a5c9 |
RewriteMap multiplex "txt:/path/to/map.mirrors"
|
|
Packit |
90a5c9 |
RewriteCond "%{REMOTE_HOST}" "([a-z]+)$" [NC]
|
|
Packit |
90a5c9 |
RewriteRule "^/(.*)$" "${multiplex:%1|http://www.example.com/}$1" [R,L]
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
## map.mirrors -- Multiplexing Map
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
de http://www.example.de/
|
|
Packit |
90a5c9 |
uk http://www.example.uk/
|
|
Packit |
90a5c9 |
com http://www.example.com/
|
|
Packit |
90a5c9 |
##EOF##
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
Discussion
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
This ruleset relies on
|
|
Packit |
90a5c9 |
HostNameLookups
|
|
Packit |
90a5c9 |
being set on , which can be
|
|
Packit |
90a5c9 |
a significant performance hit.
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
The RewriteCond
|
|
Packit |
90a5c9 |
directive captures the last portion of the hostname of the
|
|
Packit |
90a5c9 |
requesting client - the country code - and the following RewriteRule
|
|
Packit |
90a5c9 |
uses that value to look up the appropriate mirror host in the map
|
|
Packit |
90a5c9 |
file.
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
Description:
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
We wish to provide different content based on the browser, or
|
|
Packit |
90a5c9 |
user-agent, which is requesting the content.
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
Solution:
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
We have to decide, based on the HTTP header "User-Agent",
|
|
Packit |
90a5c9 |
which content to serve. The following config
|
|
Packit |
90a5c9 |
does the following: If the HTTP header "User-Agent"
|
|
Packit |
90a5c9 |
contains "Mozilla/3", the page foo.html
|
|
Packit |
90a5c9 |
is rewritten to foo.NS.html and the
|
|
Packit |
90a5c9 |
rewriting stops. If the browser is "Lynx" or "Mozilla" of
|
|
Packit |
90a5c9 |
version 1 or 2, the URL becomes foo.20.html .
|
|
Packit |
90a5c9 |
All other browsers receive page foo.32.html .
|
|
Packit |
90a5c9 |
This is done with the following ruleset:
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
RewriteCond "%{HTTP_USER_AGENT}" "^Mozilla/3.*"
|
|
Packit |
90a5c9 |
RewriteRule "^foo\.html$" "foo.NS.html" [L]
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
RewriteCond "%{HTTP_USER_AGENT}" "^Lynx/" [OR]
|
|
Packit |
90a5c9 |
RewriteCond "%{HTTP_USER_AGENT}" "^Mozilla/[12]"
|
|
Packit |
90a5c9 |
RewriteRule "^foo\.html$" "foo.20.html" [L]
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
RewriteRule "^foo\.html$" "foo.32.html" [L]
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
Description:
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
On some webservers there is more than one URL for a
|
|
Packit |
90a5c9 |
resource. Usually there are canonical URLs (which are be
|
|
Packit |
90a5c9 |
actually used and distributed) and those which are just
|
|
Packit |
90a5c9 |
shortcuts, internal ones, and so on. Independent of which URL the
|
|
Packit |
90a5c9 |
user supplied with the request, they should finally see the
|
|
Packit |
90a5c9 |
canonical one in their browser address bar.
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
Solution:
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
We do an external HTTP redirect for all non-canonical
|
|
Packit |
90a5c9 |
URLs to fix them in the location view of the Browser and
|
|
Packit |
90a5c9 |
for all subsequent requests. In the example ruleset below
|
|
Packit |
90a5c9 |
we replace /puppies and /canines
|
|
Packit |
90a5c9 |
by the canonical /dogs .
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
RewriteRule "^/(puppies|canines)/(.*)" "/dogs/$2" [R]
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
Discussion:
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
This should really be accomplished with Redirect or RedirectMatch
|
|
Packit |
90a5c9 |
directives:
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
RedirectMatch "^/(puppies|canines)/(.*)" "/dogs/$2"
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
Description:
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
Usually the DocumentRoot
|
|
Packit |
90a5c9 |
of the webserver directly relates to the URL "/ ".
|
|
Packit |
90a5c9 |
But often this data is not really of top-level priority. For example,
|
|
Packit |
90a5c9 |
you may wish for visitors, on first entering a site, to go to a
|
|
Packit |
90a5c9 |
particular subdirectory /about/ . This may be accomplished
|
|
Packit |
90a5c9 |
using the following ruleset:
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
Solution:
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
We redirect the URL / to
|
|
Packit |
90a5c9 |
/about/ :
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
RewriteEngine on
|
|
Packit |
90a5c9 |
RewriteRule "^/$" "/about/" [R]
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
Note that this can also be handled using the RedirectMatch directive:
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
RedirectMatch "^/$" "http://example.com/about/"
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
Note also that the example rewrites only the root URL. That is, it
|
|
Packit |
90a5c9 |
rewrites a request for http://example.com/ , but not a
|
|
Packit |
90a5c9 |
request for http://example.com/page.html . If you have in
|
|
Packit |
90a5c9 |
fact changed your document root - that is, if all of
|
|
Packit |
90a5c9 |
your content is in fact in that subdirectory, it is greatly preferable
|
|
Packit |
90a5c9 |
to simply change your DocumentRoot
|
|
Packit |
90a5c9 |
directive, or move all of the content up one directory,
|
|
Packit |
90a5c9 |
rather than rewriting URLs.
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
Description:
|
|
Packit |
90a5c9 |
You want a single resource (say, a certain file, like index.php) to
|
|
Packit |
90a5c9 |
handle all requests that come to a particular directory, except those
|
|
Packit |
90a5c9 |
that should go to an existing resource such as an image, or a css file.
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
Solution:
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
As of version 2.2.16, you should use the FallbackResource directive for this:
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
<Directory "/var/www/my_blog">
|
|
Packit |
90a5c9 |
FallbackResource "index.php"
|
|
Packit |
90a5c9 |
</Directory>
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
However, in earlier versions of Apache, or if your needs are more
|
|
Packit |
90a5c9 |
complicated than this, you can use a variation of the following rewrite
|
|
Packit |
90a5c9 |
set to accomplish the same thing:
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
<Directory "/var/www/my_blog">
|
|
Packit |
90a5c9 |
RewriteBase "/my_blog"
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
RewriteCond "/var/www/my_blog/%{REQUEST_FILENAME}" !-f
|
|
Packit |
90a5c9 |
RewriteCond "/var/www/my_blog/%{REQUEST_FILENAME}" !-d
|
|
Packit |
90a5c9 |
RewriteRule "^" "index.php" [PT]
|
|
Packit |
90a5c9 |
</Directory>
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
If, on the other hand, you wish to pass the requested URI as a query
|
|
Packit |
90a5c9 |
string argument to index.php, you can replace that RewriteRule with:
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
RewriteRule "(.*)" "index.php?$1" [PT,QSA]
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
Note that these rulesets can be used in a .htaccess
|
|
Packit |
90a5c9 |
file, as well as in a <Directory> block.
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
Description:
|
|
Packit |
90a5c9 |
You want to capture a particular value from a query string
|
|
Packit |
90a5c9 |
and either replace it or incorporate it into another component
|
|
Packit |
90a5c9 |
of the URL.
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
Solutions:
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
Many of the solutions in this section will all use the same condition,
|
|
Packit |
90a5c9 |
which leaves the matched value in the %2 backreference. %1 is the beginining
|
|
Packit |
90a5c9 |
of the query string (up to the key of intererest), and %3 is the remainder. This
|
|
Packit |
90a5c9 |
condition is a bit complex for flexibility and to avoid double '&&' in the
|
|
Packit |
90a5c9 |
substitutions.
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
This solution removes the matching key and value:
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
# Remove mykey=???
|
|
Packit |
90a5c9 |
RewriteCond "%{QUERY_STRING}" "(.*(?:^|&))mykey=([^&]*)&?(.*)&?$"
|
|
Packit |
90a5c9 |
RewriteRule "(.*)" "$1?%1%3"
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
This solution uses the captured value in the URL subsitution,
|
|
Packit |
90a5c9 |
discarding the rest of the original query by appending a '?':
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
# Copy from query string to PATH_INFO
|
|
Packit |
90a5c9 |
RewriteCond "%{QUERY_STRING}" "(.*(?:^|&))mykey=([^&]*)&?(.*)&?$"
|
|
Packit |
90a5c9 |
RewriteRule "(.*)" "$1/products/%2/?" [PT]
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
This solution checks the captured value in a subsequent condition:
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
# Capture the value of mykey in the query string
|
|
Packit |
90a5c9 |
RewriteCond "%{QUERY_STRING}" "(.*(?:^|&))mykey=([^&]*)&?(.*)&?$"
|
|
Packit |
90a5c9 |
RewriteCond "%2" !=not-so-secret-value
|
|
Packit |
90a5c9 |
RewriteRule "(.*)" - [F]
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
This solution shows the reverse of the previous ones, copying
|
|
Packit |
90a5c9 |
path components (perhaps PATH_INFO) from the URL into the query string.
|
|
Packit |
90a5c9 |
# The desired URL might be /products/kitchen-sink, and the script expects
|
|
Packit |
90a5c9 |
# /path?products=kitchen-sink.
|
|
Packit |
90a5c9 |
RewriteRule "^/?path/([^/]+)/([^/]+)" "/path?$1=$2" [PT]
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
Available Languages: en |
|
|
Packit |
90a5c9 |
fr
|
|
Packit |
90a5c9 |
Notice: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 again 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 Freenode, or sent to our mailing lists.
|
|
Packit |
90a5c9 |
<script type="text/javascript">
|
|
Packit |
90a5c9 |
var comments_shortname = 'httpd';
|
|
Packit |
90a5c9 |
var comments_identifier = 'http://httpd.apache.org/docs/2.4/rewrite/remapping.html';
|
|
Packit |
90a5c9 |
(function(w, d) {
|
|
Packit |
90a5c9 |
if (w.location.hostname.toLowerCase() == "httpd.apache.org") {
|
|
Packit |
90a5c9 |
d.write('
|
|
Packit |
90a5c9 |
var s = d.createElement('script');
|
|
Packit |
90a5c9 |
s.type = 'text/javascript';
|
|
Packit |
90a5c9 |
s.async = true;
|
|
Packit |
90a5c9 |
s.src = 'https://comments.apache.org/show_comments.lua?site=' + comments_shortname + '&page=' + comments_identifier;
|
|
Packit |
90a5c9 |
(d.getElementsByTagName('head')[0] || d.getElementsByTagName('body')[0]).appendChild(s);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
else {
|
|
Packit |
90a5c9 |
d.write('
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
})(window, document);
|
|
Packit |
90a5c9 |
//--></script>
|
|
Packit |
90a5c9 |
Copyright 2018 The Apache Software Foundation. Licensed under the Apache License, Version 2.0.
|
|
Packit |
90a5c9 |
Modules | Directives | FAQ | Glossary | Sitemap <script type="text/javascript">
|
|
Packit |
90a5c9 |
if (typeof(prettyPrint) !== 'undefined') {
|
|
Packit |
90a5c9 |
prettyPrint();
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
//--></script>
|
|
Packit |
90a5c9 |
</body></html>
|