blob: ea5e3950b631c73d4913fbc62ca68740f27f0b2c [file]
<!DOCTYPE html SYSTEM "about:legacy-compat">
<html lang="zh-cn"><head><META http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta content="width=device-width, initial-scale=1" name="viewport">
<!--
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
This file is generated from xml source: DO NOT EDIT
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
-->
<title>Apache mod_rewrite 技术细节 - Apache HTTP 服务器 版本 2.5</title>
<link href="../style/css/manual.css" rel="stylesheet" media="all" type="text/css" title="Main stylesheet">
<link href="../style/css/manual-loose-100pc.css" rel="alternate stylesheet" media="all" type="text/css" title="No Sidebar - Default font size">
<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">
<script src="../style/scripts/prettify.min.js">
</script>
<link href="../images/favicon.png" rel="shortcut icon"></head>
<body id="manual-page"><div id="page-header">
<p class="menu"><a href="../mod/">模块</a> | <a href="../mod/quickreference.html">指令</a> | <a href="https://cwiki.apache.org/confluence/display/httpd/FAQ">常见问题</a> | <a href="../glossary.html">术语</a> | <a href="../sitemap.html">网站导航</a> | <a href="https://bz.apache.org/bugzilla/enter_bug.cgi?product=Apache%20httpd-2">Report a bug</a></p>
<p class="apache">Apache HTTP 服务器版本 2.5</p>
<img alt="" src="../images/feather.png"></div>
<div class="up"><a href="./"><img title="<-" alt="<-" src="../images/left.gif"></a></div>
<div id="path">
<a href="https://www.apache.org/">Apache</a> &gt; <a href="https://httpd.apache.org/">HTTP 服务器</a> &gt; <a href="https://httpd.apache.org/docs/">文档</a> &gt; <a href="../">版本 2.5</a> &gt; <a href="./">Rewrite</a></div><div id="page-content"><div id="preamble"><h1>Apache mod_rewrite 技术细节</h1>
<button aria-label="Toggle language list" class="lang-toggle"><svg xmlns="http://www.w3.org/2000/svg" stroke-width="2" stroke="currentColor" fill="none" viewBox="0 0 24 24" height="16" width="16"><circle r="10" cy="12" cx="12"/><line y2="12" x2="22" y1="12" x1="2"/><path d="M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z"/></svg></button>
<div class="toplang">
<p><span>可用语言: </span><a href="../de/rewrite/tech.html" hreflang="de" rel="alternate" title="Deutsch">&nbsp;de&nbsp;</a> |
<a href="../en/rewrite/tech.html" hreflang="en" rel="alternate" title="English">&nbsp;en&nbsp;</a> |
<a href="../es/rewrite/tech.html" hreflang="es" rel="alternate" title="Espa&ntilde;ol">&nbsp;es&nbsp;</a> |
<a href="../fr/rewrite/tech.html" hreflang="fr" rel="alternate" title="Fran&ccedil;ais">&nbsp;fr&nbsp;</a> |
<a href="../ja/rewrite/tech.html" hreflang="ja" rel="alternate" title="Japanese">&nbsp;ja&nbsp;</a> |
<a href="../ko/rewrite/tech.html" hreflang="ko" rel="alternate" title="Korean">&nbsp;ko&nbsp;</a> |
<a href="../tr/rewrite/tech.html" hreflang="tr" rel="alternate" title="T&uuml;rk&ccedil;e">&nbsp;tr&nbsp;</a> |
<a href="../zh-cn/rewrite/tech.html" title="Simplified Chinese">&nbsp;zh-cn&nbsp;</a></p>
</div>
<div class="outofdate">此翻译可能过期。要了解最近的更改,请阅读英文版。</div>
<p>本文档讨论 <code class="module"><a href="../mod/mod_rewrite.html">mod_rewrite</a></code> 和 URL 匹配的一些技术细节。</p>
</div>
<div id="quickview"><ul id="toc"><li><img alt="" src="../images/down.gif"> <a href="#InternalAPI">API 阶段</a></li>
<li><img alt="" src="../images/down.gif"> <a href="#InternalRuleset">规则集处理</a></li>
</ul><h3>参见</h3><ul class="seealso"><li><a href="../mod/mod_rewrite.html">模块文档</a></li><li><a href="intro.html">mod_rewrite 简介</a></li><li><a href="remapping.html">重定向和重映射</a></li><li><a href="access.html">访问控制</a></li><li><a href="vhosts.html">虚拟主机</a></li><li><a href="proxy.html">代理</a></li><li><a href="rewritemap.html">使用 RewriteMap</a></li><li><a href="advanced.html">高级技术</a></li><li><a href="avoid.html">何时不使用 mod_rewrite</a></li></ul></div>
<div class="top"><a href="#page-header"><img alt="top" src="../images/up.gif"></a></div>
<div class="section">
<h2 id="InternalAPI">API 阶段 <a title="Permanent link" href="#InternalAPI" class="permalink">&para;</a></h2>
<p>Apache HTTP 服务器分多个阶段处理请求。在每个阶段,
一个或多个模块可能被调用来处理请求生命周期的那个部分。
这些阶段包括 URL 到文件名转换、身份验证、授权、内容和日志记录等。
(这不是一个详尽的列表。)</p>
<p><code class="module"><a href="../mod/mod_rewrite.html">mod_rewrite</a></code> 在其中两个阶段(或通常所说的"钩子")
中起作用,以影响 URL 的重写方式。</p>
<p>首先,它使用 URL 到文件名转换钩子,该钩子在 HTTP
请求被读取之后、但在任何授权开始之前触发。其次,它使用 Fixup 钩子,
该钩子在授权阶段之后、在目录级配置文件(<code>.htaccess</code> 文件)
被读取之后、但在内容处理程序被调用之前触发。</p>
<p>当请求进入并确定了对应的服务器或虚拟主机后,
重写引擎开始处理出现在服务器级配置中的所有 <code class="module"><a href="../mod/mod_rewrite.html">mod_rewrite</a></code>
指令。(即在主服务器配置文件和 <code class="directive"><a href="../mod/core.html#virtualhost">&lt;Virtualhost&gt;</a></code> 配置段中。)
这发生在 URL 到文件名转换阶段。</p>
<p>几个步骤之后,一旦找到最终的数据目录,
就会应用目录级配置指令(<code>.htaccess</code> 文件和 <code class="directive"><a href="../mod/core.html#directory">&lt;Directory&gt;</a></code> 块)。
这发生在 Fixup 阶段。</p>
<p>在每种情况下,<code class="module"><a href="../mod/mod_rewrite.html">mod_rewrite</a></code> 都会将
<code>REQUEST_URI</code> 重写为新的 URL 或文件名。</p>
<p>在目录级上下文中(即在 <code>.htaccess</code> 文件和
<code>Directory</code> 块中),这些规则在 URL
已经被转换为文件名之后才被应用。因此,<code class="module"><a href="../mod/mod_rewrite.html">mod_rewrite</a></code>
最初用来与 <code class="directive"><a href="../mod/mod_rewrite.html#rewriterule">RewriteRule</a></code>
指令进行比较的 URL 路径是转换后的完整文件系统路径,
其中当前目录路径(包括尾部斜杠)已从前面被移除。</p>
<p>举例来说:如果规则位于 /var/www/foo/.htaccess 中,
正在处理对 /foo/bar/baz 的请求,则表达式 ^bar/baz$ 将会匹配。</p>
<p>如果在目录级上下文中进行了替换,将使用新的 URL
发出新的内部子请求,重新开始请求阶段的处理。如果替换是相对路径,
<code class="directive"><a href="../mod/mod_rewrite.html#rewritebase">RewriteBase</a></code>
指令决定在替换前面添加的 URL 路径前缀。在目录级上下文中,
必须注意创建的规则最终(在未来某轮目录级重写处理中)不会执行替换,
以避免循环。(参见 <a href="https://cwiki.apache.org/confluence/display/httpd/RewriteLooping">RewriteLooping</a>
以进一步讨论此问题。)</p>
<p>由于在目录级上下文中对 URL 进行了进一步操作,
你需要注意在该上下文中以不同方式编写重写规则。特别要记住,
前导目录路径将从你的重写规则所看到的 URL 中被去除。
请参考下面的示例以进一步说明。</p>
<table class="bordered">
<tr>
<th>规则位置</th>
<th>规则</th>
</tr>
<tr>
<td>VirtualHost 配置段</td>
<td>RewriteRule "^/images/(.+)\.jpg" "/images/$1.gif"</td>
</tr>
<tr>
<td>文档根目录下的 .htaccess 文件</td>
<td>RewriteRule "^images/(.+)\.jpg" "images/$1.gif"</td>
</tr>
<tr>
<td>images 目录下的 .htaccess 文件</td>
<td>RewriteRule "^(.+)\.jpg" "$1.gif"</td>
</tr>
</table>
<p>要更深入地了解 <code class="module"><a href="../mod/mod_rewrite.html">mod_rewrite</a></code> 如何在不同上下文中操作 URL,
你应该查阅重写期间生成的<a href="../mod/mod_rewrite.html#logging">日志条目</a></p>
</div><div class="top"><a href="#page-header"><img alt="top" src="../images/up.gif"></a></div>
<div class="section">
<h2 id="InternalRuleset">规则集处理 <a title="Permanent link" href="#InternalRuleset" class="permalink">&para;</a></h2>
<p>现在当 <code class="module"><a href="../mod/mod_rewrite.html">mod_rewrite</a></code> 在这两个 API 阶段被触发时,
它从其配置结构中读取已配置的规则集(该配置结构在服务器级上下文中于启动时创建,
或在目录级上下文中于 Apache 内核的目录遍历过程中创建)。
然后使用包含的规则集(一条或多条规则及其条件)启动 URL 重写引擎。
URL 重写引擎本身的操作在两种配置上下文中完全相同。
只有最终结果的处理方式不同。</p>
<p>规则集中规则的顺序很重要,因为重写引擎以一种特殊的(且不太直观的)
顺序处理它们。规则如下:重写引擎逐条遍历规则集中的规则
<code class="directive"><a href="../mod/mod_rewrite.html#rewriterule">RewriteRule</a></code> 指令),
当某条规则匹配时,它会可选地遍历对应的条件
<code>RewriteCond</code> 指令)。由于历史原因,
条件写在前面,因此控制流程有点绕。参见图 1 了解更多细节。</p>
<p class="figure">
<img src="../images/rewrite_process_uri.png" alt="RewriteRule 和 RewriteCond 匹配流程"><br>
<dfn>图 1:</dfn>重写规则集的控制流程
</p>
<p>首先,URL 与每条规则的<em>模式</em>进行匹配。如果匹配失败,
<code class="module"><a href="../mod/mod_rewrite.html">mod_rewrite</a></code> 立即停止处理该规则,并继续处理下一条规则。
如果<em>模式</em>匹配成功,<code class="module"><a href="../mod/mod_rewrite.html">mod_rewrite</a></code>
会查找对应的规则条件(RewriteCond 指令,
在配置中紧接在 RewriteRule 之前出现)。
如果没有条件,则用从字符串<em>替换</em>构造的新值替换 URL,
并继续其规则循环。但如果存在条件,则启动一个内部循环,
按照条件列出的顺序处理它们。对于条件,逻辑是不同的:
我们不是将模式与当前 URL 匹配。而是首先通过展开变量、
反向引用、映射查找<em></em>来创建一个字符串 <em>TestString</em>
然后尝试将 <em>CondPattern</em> 与之匹配。如果模式不匹配,
则整组条件和对应规则都失败。如果模式匹配,则处理下一个条件,
直到没有更多条件为止。如果所有条件都匹配,
则继续用<em>替换</em>替换 URL。</p>
</div></div>
<div class="bottomlang">
<p><span>可用语言: </span><a href="../de/rewrite/tech.html" hreflang="de" rel="alternate" title="Deutsch">&nbsp;de&nbsp;</a> |
<a href="../en/rewrite/tech.html" hreflang="en" rel="alternate" title="English">&nbsp;en&nbsp;</a> |
<a href="../es/rewrite/tech.html" hreflang="es" rel="alternate" title="Espa&ntilde;ol">&nbsp;es&nbsp;</a> |
<a href="../fr/rewrite/tech.html" hreflang="fr" rel="alternate" title="Fran&ccedil;ais">&nbsp;fr&nbsp;</a> |
<a href="../ja/rewrite/tech.html" hreflang="ja" rel="alternate" title="Japanese">&nbsp;ja&nbsp;</a> |
<a href="../ko/rewrite/tech.html" hreflang="ko" rel="alternate" title="Korean">&nbsp;ko&nbsp;</a> |
<a href="../tr/rewrite/tech.html" hreflang="tr" rel="alternate" title="T&uuml;rk&ccedil;e">&nbsp;tr&nbsp;</a> |
<a href="../zh-cn/rewrite/tech.html" title="Simplified Chinese">&nbsp;zh-cn&nbsp;</a></p>
</div><div id="footer">
<p class="apache">Copyright 2026 The Apache Software Foundation.<br>基于 <a href="https://www.apache.org/licenses/LICENSE-2.0">Apache License, Version 2.0</a> 许可证.</p>
<p class="menu"><a href="../mod/">模块</a> | <a href="../mod/quickreference.html">指令</a> | <a href="https://cwiki.apache.org/confluence/display/httpd/FAQ">常见问题</a> | <a href="../glossary.html">术语</a> | <a href="../sitemap.html">网站导航</a> | <a href="https://bz.apache.org/bugzilla/enter_bug.cgi?product=Apache%20httpd-2">Report a bug</a></p></div><script><!--//--><![CDATA[//><!--
if (typeof(prettyPrint) !== 'undefined') {
prettyPrint();
}
var langToggle = document.querySelector('.lang-toggle');
var topLang = document.querySelector('.toplang');
if (langToggle && topLang) {
langToggle.addEventListener('click', function() { topLang.classList.toggle('open'); });
}
var qv = document.getElementById('quickview');
if (qv) {
document.body.appendChild(qv);
var qvBtn = document.createElement('button');
qvBtn.className = 'qv-toggle';
qvBtn.setAttribute('aria-label', 'Toggle page navigation');
qvBtn.innerHTML = '&#9776;';
document.body.appendChild(qvBtn);
qvBtn.addEventListener('click', function() {
var isOpen = qv.classList.toggle('open');
if (isOpen) {
qv.style.top = window.scrollY + 10 + 'px';
}
});
window.addEventListener('scroll', function() { qv.classList.remove('open'); });
}
//--><!]]></script>
</body></html>