添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

本文件是对 mod_rewrite 参考文档 。它描述了如何使用 mod_rewrite 重定向和重新映射请求。这包括mod_rewrite常用用法的许多示例,包括每种用法的详细说明。

请注意,这些示例中的许多示例在您的特定服务器配置中都不会起作用,因此,理解它们,而不只是将示例剪切并粘贴到您的配置中,这一点很重要。

从旧到新(内部)

假设我们最近已将页面重命名 foo.html bar.html 并且现在想提供旧的URL以实现向后兼容。但是,我们希望旧URL的用户甚至无法识别页面已被重命名-也就是说,我们不希望在其浏览器中更改地址。

我们通过以下规则在内部将旧网址重写为新网址:

RewriteEngine  on
RewriteRule    "^/foo\.html$"  "/bar.html" [PT]

再次假设我们最近已重命名页面 foo.html bar.html 并且现在想提供旧的URL以实现向后兼容。但是这一次,我们希望旧URL的用户得到新的提示,即他们的浏览器的“位置”字段也应更改。

我们强制将HTTP重定向到新URL,从而导致浏览器发生更改,因此用户可以查看:

RewriteEngine  on
RewriteRule    "^/foo\.html$"  "bar.html"  [R]

与上面的 内部 示例相比,在此示例中,我们可以简单地使用Redirect指令。在较早的示例中使用了mod_rewrite,以便从客户端隐藏重定向:

Redirect "/foo.html" "/bar.html"
#With mod_rewrite
RewriteEngine on
RewriteRule   "^/docs/(.+)"  "http://new.example.com/docs/$1"  [R,L]
#With RedirectMatch
RedirectMatch "^/docs/(.*)" "http://new.example.com/docs/$1"
#With Redirect
Redirect "/docs/" "http://new.example.com/docs/"

我们只是将URL重写为CGI脚本,然后将处理程序强制为 cgi-script, 以便将其作为CGI程序执行。这样一来 /~quux/foo.html 在内部导致对 /~quux/foo.cgi

RewriteEngine  on
RewriteBase    "/~quux/"
RewriteRule    "^foo\.html$"  "foo.cgi"  [H=cgi-script]

我们将该名称重写为其基名称,并测试是否存在新扩展名。如果存在,则使用该名称,否则将URL重写为其原始状态。

#   backward compatibility ruleset for
#   rewriting document.html to document.php
#   when and only when document.php exists
<Directory "/var/www/htdocs">
    RewriteEngine on
    RewriteBase "/var/www/htdocs"
    RewriteCond "$1.php" -f
    RewriteCond "$1.html" !-f
    RewriteRule "^(.*).html$" "$1.php"
</Directory>

本示例通过利用规则集的执行顺序,使用了mod_rewrite经常被忽略的功能。特别是,mod_rewrite在评估RewriteCond指令之前先评估RewriteRule的左侧。因此,在评估RewriteCond指令时已经定义了$ 1。这使我们可以测试原始文件的存在( document.html )和目标( document.php )文件使用相同的基本文件名。

此规则集旨在在每个目录的上下文中使用(在 块中或在.htaccess文件中),以便 -f 检查正在寻找正确的目录路径。您可能需要设置一个 RewriteBase 指令以指定您正在使用的目录库。

该规则的目标是强制使用特定主机名,而不是可能用于访问同一站点的其他主机名。例如,如果您希望强制使用 www.example.com 而不是 example.com ,则可以使用以下配方的变体。

解决此问题的最佳方法根本不涉及mod_rewrite,而是使用 Redirect 放置在虚拟主机中的非规范主机名的指令。

<VirtualHost *:80>
  ServerName undesired.example.com
  ServerAlias example.com notthis.example.com
  Redirect "/" "http://www.example.com/"
</VirtualHost>
<VirtualHost *:80>
  ServerName www.example.com
</VirtualHost>

您也可以使用 指示:

<If "%{HTTP_HOST} != 'www.example.com'">
    Redirect "/" "http://www.example.com/"

或者,例如,要将您的网站的一部分重定向到HTTPS,您可以执行以下操作:

<If "%{SERVER_PROTOCOL} != 'HTTPS'">
    Redirect "/admin/" "https://www.example.com/admin/"

如果出于某种原因您仍然想要使用mod_rewrite -例如,如果您需要使用它来处理更多的RewriteRules,则可以使用以下配方之一。

对于运行在80以外的端口上的站点:

RewriteCond "%{HTTP_HOST}"   "!^www\.example\.com" [NC]
RewriteCond "%{HTTP_HOST}"   "!^$"
RewriteCond "%{SERVER_PORT}" "!^80$"
RewriteRule "^/?(.*)"        "http://www.example.com:%{SERVER_PORT}/$1" [L,R,NE]

对于在端口80上运行的站点

RewriteCond "%{HTTP_HOST}"   "!^www\.example\.com" [NC]
RewriteCond "%{HTTP_HOST}"   "!^$"
RewriteRule "^/?(.*)"        "http://www.example.com/$1" [L,R,NE]

如果您想为所有域名一般做到这一点-那就是,如果你想重定向的example.com www.example.comexample.com的所有可能的值,可以使用下面的方法:

RewriteCond "%{HTTP_HOST}" "!^www\." [NC]
RewriteCond "%{HTTP_HOST}" "!^$"
RewriteRule "^/?(.*)"      "http://www.%{HTTP_HOST}/$1" [L,R,NE]

这些规则集将在您的主服务器配置文件中或在.htaccess文件放在DocumentRoot服务器。

# first try to find it in dir1/... # ...and if found stop and be happy: RewriteCond "%{DOCUMENT_ROOT}/dir1/%{REQUEST_URI}" -f RewriteRule "^(.+)" "%{DOCUMENT_ROOT}/dir1/$1" [L] # second try to find it in dir2/... # ...and if found stop and be happy: RewriteCond "%{DOCUMENT_ROOT}/dir2/%{REQUEST_URI}" -f RewriteRule "^(.+)" "%{DOCUMENT_ROOT}/dir2/$1" [L] # else go on for other Alias or ScriptAlias directives, # etc. RewriteRule "^" "-" [PT]

查看发出请求的客户的主机名,我们确定他们来自哪个国家。如果我们无法在其IP地址上进行查找,我们将退回到默认服务器。

我们将使用RewriteMap指令来构建我们希望使用的服务器列表。

HostnameLookups on
RewriteEngine on
RewriteMap    multiplex         "txt:/path/to/map.mirrors"
RewriteCond   "%{REMOTE_HOST}"  "([a-z]+)$" [NC]
RewriteRule   "^/(.*)$"  "${multiplex:%1|http://www.example.com/}$1"  [R,L]

## map.mirrors -- Multiplexing Map

de http://www.example.de/
uk http://www.example.uk/
com http://www.example.com/
##EOF##

该规则集依赖HostNameLookups被设置on ,这可能会严重影响性能。

RewriteCond指令捕获请求客户端的主机名的最后一部分-国家/地区代码-并且以下RewriteRule使用该值在映射文件中查找适当的镜像主机。

我们必须根据HTTP标头“ User-Agent”确定要提供的内容。以下配置执行以下操作:如果HTTP标头“ User-Agent”包含“ Mozilla / 3”,则页面foo.html被重写为foo.NS.html并且重写停止。如果浏览器是版本1或2的“ Lynx”或“ Mozilla”,则URL变为foo.20.html 。所有其他浏览器都接收页面foo.32.html 。这是通过以下规则集完成的:

RewriteCond "%{HTTP_USER_AGENT}"  "^Mozilla/3.*"
RewriteRule "^foo\.html$"         "foo.NS.html"          [L]
RewriteCond "%{HTTP_USER_AGENT}"  "^Lynx/" [OR]
RewriteCond "%{HTTP_USER_AGENT}"  "^Mozilla/[12]"
RewriteRule "^foo\.html$"         "foo.20.html"          [L]
RewriteRule "^foo\.html$"         "foo.32.html"          [L]

在某些Web服务器上,一个资源有多个URL。通常,存在规范的URL(实际使用和分发的URL)以及仅仅是快捷方式,内部的URL等等。无论用户随请求提供了哪个URL,最终他们都应该在浏览器地址栏中看到规范的URL。

我们对所有非规范URL进行外部HTTP重定向,以在浏览器的位置视图以及所有后续请求中修复它们。在下面的示例规则集中,我们将替换/puppies/canines通过规范/dogs

RewriteRule   "^/(puppies|canines)/(.*)"    "/dogs/$2"  [R]
这实际上应该使用Redirect或RedirectMatch指令完成:
RedirectMatch "^/(puppies|canines)/(.*)" "/dogs/$2"

通常情况下DocumentRoot网络服务器的地址直接与“ / ”。但是通常这些数据并不是真正的最高优先级。例如,您可能希望访问者在首次进入网站时进入特定的子目录/about/ 。这可以使用以下规则集来完成:

我们重定向URL //about/

RewriteEngine on
RewriteRule   "^/$"  "/about/"  [R]

请注意,这也可以使用RedirectMatch指示:

RedirectMatch "^/$" "http://example.com/about/"

另请注意,该示例仅重写根URL。也就是说,它重写了http://example.com/ ,但不要求http://example.com/page.html 。如果实际上已经更改了文档根目录-也就是说,如果所有内容实际上都在该子目录中,那么最好简单地更改您的文档根目录DocumentRoot指令,或将所有内容移动到一个目录中,而不是重写URL。

RewriteCond "/var/www/my_blog/%{REQUEST_FILENAME}" !-f RewriteCond "/var/www/my_blog/%{REQUEST_FILENAME}" !-d RewriteRule "^" "index.php" [PT] </Directory>

另一方面,如果您希望将请求的URI作为查询字符串参数传递给index.php,则可以将该RewriteRule替换为:

RewriteRule "(.*)" "index.php?$1" [PT,QSA]

请注意,这些规则集可以在 .htaccess 文件,以及成 块。

解决方案:

本节中的许多解决方案都将使用相同的条件,这会将匹配的值保留在%2反向引用中。 %1是查询字符串的开头(取决于兴趣关键字),而%3是其余部分。对于灵活性和避免替换中使用双'&&'而言,此条件有点复杂。

  • 此解决方案删除匹配的键和值:
    # Remove mykey=???
    RewriteCond "%{QUERY_STRING}" "(.*(?:^|&))mykey=([^&]*)&?(.*)&?$"
    RewriteRule "(.*)" "$1?%1%3"
  • 此解决方案使用URL替换中的捕获值,并通过附加'?来丢弃其余的原始查询。':
    # Copy from query string to PATH_INFO
    RewriteCond "%{QUERY_STRING}" "(.*(?:^|&))mykey=([^&]*)&?(.*)&?$"
    RewriteRule "(.*)" "$1/products/%2/?" [PT]
  • 此解决方案在随后的条件下检查捕获的值:
    # Capture the value of mykey in the query string
    RewriteCond "%{QUERY_STRING}" "(.*(?:^|&))mykey=([^&]*)&?(.*)&?$"
    RewriteCond "%2" !=not-so-secret-value 
    RewriteRule "(.*)" - [F]
  • 此解决方案与前面的解决方案相反,将路径部分(也许是PATH_INFO)从URL复制到查询字符串中。
    # The desired URL might be /products/kitchen-sink, and the script expects
    # /path?products=kitchen-sink.
    RewriteRule "^/?path/([^/]+)/([^/]+)" "/path?$1=$2" [PT]
  •