blob: fc3fb0356d34cba384f3e999288b127ed61759c5 [file]
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE manualpage SYSTEM "../style/manualpage.dtd">
<?xml-stylesheet type="text/xsl" href="../style/manual.zh-cn.xsl"?>
<!-- English Revision: 1933071:1934233 (outdated) -->
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<manualpage metafile="avoid.xml.meta">
<parentdocument href="./">Rewrite</parentdocument>
<title>何时不使用 mod_rewrite</title>
<summary>
<p>本文档是 <module>mod_rewrite</module>
<a href="../mod/mod_rewrite.html">参考文档</a>的补充。它描述了关于
<module>mod_rewrite</module> 最重要的概念之一——
即何时应避免使用它。</p>
<p><module>mod_rewrite</module> 应被视为最后的手段,
当其他替代方案不能满足需求时才使用。在有更简单替代方案的情况下使用它,
会导致配置混乱、脆弱且难以维护。
了解有哪些替代方案可用是掌握 <module>mod_rewrite</module> 的重要一步。</p>
<p>请注意,这些示例中的许多不会在你的特定服务器配置中直接生效,
因此理解它们非常重要,而不仅仅是将示例复制粘贴到你的配置中。</p>
<p>最常见的适合使用 <module>mod_rewrite</module> 的情况是,
最佳解决方案需要访问服务器配置文件,而你没有该访问权限。
某些配置指令只能在服务器配置文件中使用。因此,
如果你处于只能使用 .htaccess 文件的托管环境中,
你可能需要借助 <module>mod_rewrite</module></p>
</summary>
<seealso><a href="../mod/mod_rewrite.html">模块文档</a></seealso>
<seealso><a href="intro.html">mod_rewrite 简介</a></seealso>
<seealso><a href="remapping.html">重定向和重映射</a></seealso>
<seealso><a href="access.html">访问控制</a></seealso>
<seealso><a href="vhosts.html">虚拟主机</a></seealso>
<seealso><a href="proxy.html">代理</a></seealso>
<seealso><a href="rewritemap.html">使用 RewriteMap</a></seealso>
<seealso><a href="advanced.html">高级技术</a></seealso>
<!--<seealso><a href="avoid.html">何时不使用 mod_rewrite</a></seealso>-->
<section id="redirect">
<title>简单重定向</title>
<p><module>mod_alias</module> 提供了 <directive
module="mod_alias">Redirect</directive><directive
module="mod_alias">RedirectMatch</directive> 指令,
它们提供了将一个 URL 重定向到另一个 URL 的方法。
这种简单的将一个 URL 或一类 URL 重定向到其他地方的操作,
应使用这些指令而不是
<directive module="mod_rewrite">RewriteRule</directive> 来完成。
<code>RedirectMatch</code> 允许你在重定向条件中包含正则表达式,
提供了使用 <code>RewriteRule</code> 的许多好处。</p>
<p><code>RewriteRule</code> 的一个常见用途是重定向整类 URL。
例如,<code>/one</code> 目录中的所有 URL 必须重定向到
<code>http://one.example.com/</code>,或者所有 <code>http</code>
请求必须重定向到 <code>https</code></p>
<p>这些情况更适合使用 <code>Redirect</code> 指令处理。
请记住,<code>Redirect</code> 会保留路径信息。也就是说,
对 URL <code>/one</code> 的重定向也会重定向其下的所有 URL,
例如 <code>/one/two.html</code><code>/one/three/four.html</code></p>
<p>要将 <code>/one</code> 下的 URL 重定向到
<code>http://one.example.com</code>,请执行以下操作:</p>
<highlight language="config">
Redirect "/one/" "http://one.example.com/"
</highlight>
<p>要将一个主机名重定向到另一个,例如将
<code>example.com</code> 重定向到 <code>www.example.com</code>
请参阅<a href="remapping.html#canonicalhost">规范主机名</a>方案。</p>
<p>要将 <code>http</code> URL 重定向到 <code>https</code>
请执行以下操作:</p>
<highlight language="config">
&lt;VirtualHost *:80&gt;
ServerName www.example.com
Redirect "/" "https://www.example.com/"
&lt;/VirtualHost&gt;
&lt;VirtualHost *:443&gt;
ServerName www.example.com
# ... SSL 配置放在这里
&lt;/VirtualHost&gt;
</highlight>
<p>当同一作用域中存在其他 <code>RewriteRule</code> 指令时,
使用 <code>RewriteRule</code> 来完成此任务可能是合适的。
这是因为,当 <code>Redirect</code><code>RewriteRule</code>
指令在同一作用域中时,无论它们在配置文件中的出现顺序如何,
<code>RewriteRule</code> 指令都会先执行。</p>
<p>对于 <em>http 到 https</em> 的重定向,
当你无权访问主服务器配置文件,
而被迫在 <code>.htaccess</code> 文件中执行此任务时,
使用 <code>RewriteRule</code> 是合适的。</p>
</section>
<section id="alias"><title>URL 别名</title>
<p><directive module="mod_alias">Alias</directive>
指令提供了从 URI 到目录的映射——通常是
<directive module="core">DocumentRoot</directive> 之外的目录。
虽然可以使用 <module>mod_rewrite</module> 执行此映射,
但出于简便性和性能原因,<directive module="mod_alias">Alias</directive>
是首选方法。</p>
<example><title>使用 Alias</title>
<highlight language="config">
Alias "/cats" "/var/www/virtualhosts/felines/htdocs"
</highlight>
</example>
<p>
当你无权访问服务器配置文件时,使用 <module>mod_rewrite</module>
执行此映射可能是合适的。Alias 只能在服务器或虚拟主机上下文中使用,
不能在 <code>.htaccess</code> 文件中使用。
</p>
<p>如果你的服务器启用了 <code>Options FollowSymLinks</code>
符号链接将是实现同样目标的另一种方式。</p>
</section>
<section id="vhosts"><title>虚拟主机</title>
<p>虽然可以<a href="vhosts.html">使用 mod_rewrite 处理虚拟主机</a>
但这很少是正确的方式。创建单独的
<directive module="core" type="section">VirtualHost</directive>
块几乎总是正确的做法。如果你有大量的虚拟主机,
可以考虑使用 <module>mod_vhost_alias</module> 来自动创建这些主机。</p>
<p><module>mod_macro</module> 等模块对于动态创建大量虚拟主机也很有用。</p>
<p>当你使用的托管服务不提供服务器配置文件的访问权限,
你只能使用 <code>.htaccess</code> 文件进行配置时,
使用 <module>mod_rewrite</module> 创建虚拟主机可能是合适的。</p>
<p>请参阅<a href="vhosts.html">使用 mod_rewrite 的虚拟主机</a>文档,
了解如何实现此目的(如果这仍然看起来是正确的方法)。</p>
</section>
<section id="proxy"><title>简单代理</title>
<p><directive module="mod_rewrite">RewriteRule</directive> 提供了 <a
href="flags.html#flag_p">[P]</a> 标志,用于将重写后的 URI 通过
<module>mod_proxy</module> 传递。</p>
<highlight language="config">
RewriteRule "^/?images(.*)" "http://imageserver.local/images$1" [P]
</highlight>
<p>但是,在许多情况下,当不需要实际的模式匹配时(如上面的示例所示),
<directive module="mod_proxy">ProxyPass</directive> 指令是更好的选择。
上面的示例可以表示为:</p>
<highlight language="config">
ProxyPass "/images/" "http://imageserver.local/images/"
</highlight>
<p>请注意,无论你使用
<directive module="mod_rewrite">RewriteRule</directive> 还是
<directive module="mod_proxy">ProxyPass</directive>
你仍然需要使用
<directive module="mod_proxy">ProxyPassReverse</directive>
指令来捕获后端服务器发出的重定向:</p>
<highlight language="config">
ProxyPassReverse "/images/" "http://imageserver.local/images/"
</highlight>
<p>当同一作用域中有其他 <code>RewriteRule</code> 生效时,
你可能需要使用 <code>RewriteRule</code> 代替,
因为 <code>RewriteRule</code> 通常会在 <code>ProxyPass</code>
之前生效,可能会抢先处理你要完成的操作。</p>
</section>
<section id="setenv"><title>环境变量测试</title>
<p><module>mod_rewrite</module> 经常用于根据特定环境变量或请求头
是否存在来执行特定操作。使用
<directive module="core" type="section">If</directive>
指令可以更高效地完成此操作。</p>
<p>例如,考虑使用 <directive>RewriteRule</directive>
来强制使用规范主机名(如 <code>www.example.com</code> 而不是
<code>example.com</code>)的常见场景。可以使用
<directive module="core" type="section">If</directive>
指令来完成,如下所示:</p>
<highlight language="config">
&lt;If "req('Host') != 'www.example.com'"&gt;
Redirect "/" "http://www.example.com/"
&lt;/If&gt;
</highlight>
<p>此技术可用于根据任何请求头、响应头或环境变量执行操作,
在许多常见场景中替代 <module>mod_rewrite</module></p>
<p>特别请参阅<a href="../expr.html">表达式求值文档</a>
了解在 <directive module="core" type="section">If</directive>
配置段和某些其他指令中可以使用哪些类型的表达式。</p>
</section>
</manualpage>