📄 mod_rewrite+.html
字号:
<p>更多有关正则表达式的资料请参见perl正则表达式手册页("<a href="http://www.perldoc.com/perl5.6.1/pod/perlre.html">perldoc
perlre</a>"). 如果你对正则表达式的更详细的资料及其变种(POSIX regex <em>等.</em>)感兴趣,
请参见以下专著:</p>
<p class="indent">
<em>Mastering Regular Expressions</em><br />
Jeffrey E.F. Friedl<br />
Nutshell Handbook Series<br />
O'Reilly & Associates, Inc. 1997<br />
ISBN 1-56592-257-3<br />
</p>
<p>另外,在mod_rewrite中,还可以使用否字符('<code>!</code>')的pattern前缀,以实现pattern的反转。
比如:``<em>如果当前URL<strong>不</strong>与pattern相匹配</em>''.
它用于使用否pattern较容易描述的需要排除的某些情况,或者作为最后一条规则。</p>
<div class="note"><h3>注意</h3>
使用否字符以反转pattern时,pattern中不能使用分组的通配成分。
由于pattern不匹配而使分组的内容是空的,所以它是不可能实现的。
因此,如果使用了否pattern,那么后继的字符串中就不能使用<code>$N</code>!
</div>
<p><a id="rhs" name="rhs">重写规则中的<em>Substitution</em></a>是,
当原始URL与<em>Pattern</em>相匹配时,用以替代(或替换)的字符串。
除了纯文本,还可以使用</p>
<ol>
<li><code>$N</code> 反向引用RewriteRule的pattern</li>
<li><code>%N</code> 反向引用最后匹配的RewriteCond pattern</li>
<li>规则条件测试字符串中(<code>%{VARNAME}</code>)的服务器变量</li>
<li><a href="#mapfunc">映射函数</a>调用(<code>${mapname:key|default}</code>)</li>
</ol>
<p>反向引用的<code>$</code><strong>N</strong>
(<strong>N</strong>=0..9) 是指用<em>Pattern</em>所匹配的第<strong>N</strong>组的内容去替换URL。
服务器变量与<code>RewriteCond</code>指令的<em>TestString</em>相同。
映射函数由<code>RewriteMap</code>指令所决定,其说明也参见该指令。
这三种类型变量按上面列表中的顺序被扩展。</p>
<p>如上所述,所有的重写规则都是(按配置文件中的定义顺序)作用于<em>Substitution</em>的。
URL被<em>Substitution</em><strong>完全地替换</strong>,并继续处理直到所有规则处理完毕,
除非用<code><strong>L</strong></code>标记显式地终结 - 见下文。</p>
<p>'<code>-</code>'是一个特殊的替换串,意思是<strong>不要替换</strong>!
似乎很愚蠢吧? 不, 它可以用于<strong>仅仅</strong>匹配某些URL而无须替换的情况下,<em>即</em>,
在发生替换前,允许以<strong>C</strong> (chain)标记连接的多个pattern同时起作用。</p>
<p>还有,你甚至可以在替换字符串中新建包含请求串的URL。
在替换串中使用问号,以标明其后继的成分应该被重新注入到QUERY_STRING中。
要删除一个已有的请求串,可以用问号来终结替换字符串。</p>
<div class="note"><h3>注意</h3>
一个特殊功能:
在用<code>http://</code><em>thishost</em>[<em>:thisport</em>]作为替换字段的前缀时,
<strong>mod_rewrite</strong>会把它自动剥离出去。
在配合生成主机名的映射函数使用的时候,
这个对隐含的外部重定向URL的精简化操作是有用的而且是重要的。
下面例子一节中的第一个例子有助于理解这点。
</div>
<div class="note"><h3>谨记</h3>
由于此功能的存在,以<code>http://thishost</code>为前缀的无条件外部重定向在你自己的服务器上是无效的。
要做这样一个自身的重定向,必须使用<strong>R</strong>标记 (见下文).
</div>
<p>此外,<em>Substitution</em>还可以追加特殊标记</p>
<p class="indent">
<strong><code>[</code><em>flags</em><code>]</code></strong>
</p>
<p>
作为<code>RewriteRule</code>指令的第三个参数。
<em>Flags</em>是一个包含以逗号分隔的下列标记的列表: </p>
<ul>
<li>
'<strong><code>redirect|R</code>
[=<em>code</em>]</strong>' (强制重定向 <a id="redirect" name="redirect"><strong>r</strong>edirect</a>)<br />
以<code>http://thishost[:thisport]/</code>(使新的URL成为一个URI)
为前缀的<em>Substitution</em>可以强制性执行一个外部重定向。
如果<em>code</em>没有指定,则产生一个HTTP响应代码302(临时性移动)。
如果需要使用在300-400范围内的其他响应代码,只需在此指定这个数值即可,
另外,还可以使用下列符号名称之一:
<code>temp</code> (默认的), <code>permanent</code>, <code>seeother</code>.
用它可以把规范化的URL反馈给客户端,<em>如</em>, 重写``<code>/~</code>''为
``<code>/u/</code>'',或对<code>/u/</code><em>user</em>加上斜杠,等等。<br />
<p><strong>注意:</strong> 在使用这个标记时,必须确保该替换字段是一个有效的URL!
否则,它会指向一个无效的位置! 并且要记住,此标记本身只是对URL加上
<code>http://thishost[:thisport]/</code>的前缀,重写操作仍然会继续。
通常,你会希望停止重写操作而立即重定向,则还需要使用'L'标记.</p>
</li>
<li>'<strong><code>forbidden|F</code></strong>' (强制URL为被禁止的 <strong>f</strong>orbidden)<br />
强制当前URL为被禁止的,<em>即</em>,立即反馈一个HTTP响应代码403(被禁止的)。
使用这个标记,可以链接若干RewriteConds以有条件地阻塞某些URL。</li>
<li>'<strong><code>gone|G</code></strong>' (强制URL为已废弃的 <strong>g</strong>one)<br />
强制当前URL为已废弃的,<em>即</em>,立即反馈一个HTTP响应代码410(已废弃的)。
使用这个标记,可以标明页面已经被废弃而不存在了.</li>
<li>
'<strong><code>proxy|P</code></strong>' (强制为代理 <strong>p</strong>roxy)<br />
此标记使替换成分被内部地强制为代理请求,并立即(<em>即</em>,
重写规则处理立即中断)把处理移交给<a href="mod_proxy.html">代理模块</a>。
你必须确保此替换串是一个有效的(<em>比如</em>常见的以<code>
http://</code><em>hostname</em>开头的)能够为Apache代理模块所处理的URI。
使用这个标记,可以把某些远程成分映射到本地服务器名称空间,
从而增强了<a href="mod_proxy.html#proxypass">ProxyPass</a>指令的功能。
<p>注意: 要使用这个功能,代理模块必须编译在Apache服务器中。
如果你不能确定,可以检查``<code>httpd -l</code>''的输出中是否有<code>mod_proxy.c</code>。
如果有,则mod_rewrite可以使用这个功能;
如果没有,则必须启用mod_proxy并重新编译``<code>httpd</code>''程序。</p>
</li>
<li>'<strong><code>last|L</code></strong>'
(最后一个规则 <strong>l</strong>ast)<br />
立即停止重写操作,并不再应用其他重写规则。
它对应于Perl中的<code>last</code>命令或C语言中的<code>break</code>命令。
这个标记可以阻止当前已被重写的URL为其后继的规则所重写。
举例,使用它可以重写根路径的URL('<code>/</code>')为实际存在的URL, <em>比如</em>,
'<code>/e/www/</code>'.</li>
<li>'<strong><code>next|N</code></strong>'
(重新执行 <strong>n</strong>ext round)<br />
重新执行重写操作(从第一个规则重新开始).
这时再次进行处理的URL已经不是原始的URL了,而是经最后一个重写规则处理的URL。
它对应于Perl中的<code>next</code>命令或C语言中的<code>continue</code>命令。
此标记可以重新开始重写操作,<em>即</em>, 立即回到循环的头部。<br />
<strong>但是要小心,不要制造死循环!</strong></li>
<li>'<strong><code>chain|C</code></strong>'
(与下一个规则相链接 <strong>c</strong>hained)<br />
此标记使当前规则与下一个(其本身又可以与其后继规则相链接的,
<em>并可以如此反复的</em>)规则相链接。
它产生这样一个效果: 如果一个规则被匹配,通常会继续处理其后继规则,
<em>即</em>,这个标记不起作用;如果规则<strong>不能</strong>被匹配,
则其后继的链接的规则会被忽略。比如,在执行一个外部重定向时,
对一个目录级规则集,你可能需要删除``<code>.www</code>''
(此处不应该出现``<code>.www</code>''的)。</li>
<li>
'<strong><code>type|T</code></strong>=<em>MIME-type</em>'
(强制MIME类型 <strong>t</strong>ype)<br />
强制目标文件的MIME类型为<em>MIME-type</em>。
比如,它可以用于模拟<code>mod_alias</code>中的<code>ScriptAlias</code>指令,
以内部地强制被映射目录中的所有文件的MIME类型为``<code>application/x-httpd-cgi</code>''.</li>
<li>
'<strong><code>nosubreq|NS</code></strong>' (仅用于不对内部子请求进行处理 <strong>n</strong>o internal
<strong>s</strong>ub-request)<br />
在当前请求是一个内部子请求时,此标记强制重写引擎跳过该重写规则。
比如,在<code>mod_include</code>试图搜索可能的目录默认文件(<code>index.xxx</code>)时,
Apache会内部地产生子请求。对子请求,它不一定有用的,而且如果整个规则集都起作用,
它甚至可能会引发错误。所以,可以用这个标记来排除某些规则。<br />
<p>根据你的需要遵循以下原则: 如果你使用了有CGI脚本的URL前缀,以强制它们由CGI脚本处理,
而对子请求处理的出错率(或者开销)很高,在这种情况下,可以使用这个标记。</p>
</li>
<li>'<strong><code>nocase|NC</code></strong>'
(忽略大小写 <strong>n</strong>o <strong>c</strong>ase)<br />
它使<em>Pattern</em>忽略大小写,<em>即</em>,
在<em>Pattern</em>与当前URL匹配时,'A-Z' 和'a-z'没有区别。</li>
<li>'<strong><code>qsappend|QSA</code></strong>'
(追加请求串 <strong>q</strong>uery <strong>s</strong>tring
<strong>a</strong>ppend)<br />
此标记强制重写引擎在已有的替换串中追加一个请求串,而不是简单的替换。
如果需要通过重写规则在请求串中增加信息,就可以使用这个标记。</li>
<li>
'<strong><code>noescape|NE</code></strong>'
(在输出中不对URI作转义 <strong>n</strong>o URI <strong>e</strong>scaping)<br />
此标记阻止mod_rewrite对重写结果应用常规的URI转义规则。
一般情况下,特殊字符(如'%', '$', ';'等)会被转义为等值的十六进制编码。
此标记可以阻止这样的转义,以允许百分号等符号出现在输出中,如:
<div class="example"><p><code>
RewriteRule /foo/(.*) /bar?arg=P1\%3d$1 [R,NE]
</code></p></div>
可以使'<code>/foo/zed</code>'转向到一个安全的请求'<code>/bar?arg=P1=zed</code>'.
</li>
<li>
'<strong><code>passthrough|PT</code></strong>'
(移交给下一个处理器 <strong>p</strong>ass <strong>t</strong>hrough)<br />
此标记强制重写引擎将内部结构<code>request_rec</code>中的<code>uri</code>字段设置为
<code>filename</code>字段的值,它只是一个小修改,使之能对来自其他URI到文件名翻译器的
<code>Alias</code>,<code>ScriptAlias</code>, <code>Redirect</code>
<em>等</em>指令的输出进行后续处理。举一个能说明其含义的例子:
如果要通过<code>mod_rewrite</code>的重写引擎重写<code>/abc</code>为<code>/def</code>,
然后通过<code>mod_alias</code>使<code>/def</code>转变为<code>/ghi</code>,可以这样:
<div class="example"><p><code>
RewriteRule ^/abc(.*) /def$1 [PT]<br />
Alias /def /ghi
</code></p></div>
如果省略了<code>PT</code>标记,虽然<code>mod_rewrite</code>运作正常,
<em>即</em>, 作为一个使用API的URI到文件名翻译器,
它可以重写<code>uri=/abc/...</code>为<code>filename=/def/...</code>,
但是,后续的<code>mod_alias</code>在试图作URI到文件名的翻译时,则会失效。
<p>注意: <strong>如果需要混合使用不同的包含URI到文件名翻译器的模块时,
就必须使用这个标记。</strong>。
混合使用<code>mod_alias</code>和<code>mod_rewrite</code>就是个典型的例子。</p>
<div class="note"><h3>For Apache hackers</h3>
如果当前Apache API除了URI到文件名hook之外,还有一个文件名到文件名的hook,
就不需要这个标记了! 但是,如果没有这样一个hook,则此标记是唯一的解决方案。
Apache Group讨论过这个问题,并在Apache 2.0 版本中会增加这样一个hook。
</div>
</li>
<li>'<strong><code>skip|S</code></strong>=<em>num</em>'
(跳过后继的规则 <strong>s</strong>kip)<br />
此标记强制重写引擎跳过当前匹配规则后继的<em>num</em>个规则。
它可以实现一个伪if-then-else的构造:
最后一个规则是then从句,而被跳过的<code>skip=N</code>个规则是else从句.
(它和'chain|C'标记是<strong>不同</strong>的!)</li>
<li>'<strong><code>env|E=</code></strong><em>VAR</em>:<em>VAL</em>'
(设置环境变量 <strong>e</strong>nvironment variable)<br />
此标记使环境变量<em>VAR</em>的值为<em>VAL</em>,
<em>VAL</em>可以包含可扩展的反向引用的正则表达式<code>$N</code>和<code>%N</code>。
此
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -