<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Observer Life &#187; mod_rewrite</title>
	<atom:link href="http://observerlife.com/tag/mod_rewrite/feed/" rel="self" type="application/rss+xml" />
	<link>http://observerlife.com</link>
	<description>To be a better man (Observer)</description>
	<lastBuildDate>Sun, 05 Sep 2010 16:21:09 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>Apache的Mod_rewrite学习（二）</title>
		<link>http://observerlife.com/apache%e7%9a%84mod_rewrite%e5%ad%a6%e4%b9%a0%ef%bc%88%e4%ba%8c%ef%bc%89/</link>
		<comments>http://observerlife.com/apache%e7%9a%84mod_rewrite%e5%ad%a6%e4%b9%a0%ef%bc%88%e4%ba%8c%ef%bc%89/#comments</comments>
		<pubDate>Wed, 11 Apr 2007 07:24:18 +0000</pubDate>
		<dc:creator>ycg</dc:creator>
				<category><![CDATA[Unix/Linux]]></category>
		<category><![CDATA[apache]]></category>
		<category><![CDATA[mod_rewrite]]></category>

		<guid isPermaLink="false">http://www.kedy.cn/blog/?p=147</guid>
		<description><![CDATA[　今天学习重写规则的语法。 RewriteRuleSyntax: RewriteRule Pattern Substitution [flags] 　　一条RewriteRule指令，定义一条重写规则，规则间的顺序非常重要。对Apache1.2及以后的版本，模板(pattern)是一个POSIX正则式，用以匹配当前的URL。当前的URL不一定是用记最初提交的URL，因为可能用一些规则在此规则前已经对URL进行了处理。　　对mod_rewrite来说，！是个合法的模板前缀，表示&#8220;非&#8221;的意思，这对描述&#8220;不满足某种匹配条件&#8221;的情况非常方便，或用作最后一条默认规则。当使用！时，不能在模板中有分组的通配符，也不能做后向引用。　　当匹配成功后，Substitution会被用来替换相应的匹配，它除了可以是普通的字符串以外，还可以包括： $N,引用RewriteRule模板中匹配的相关字串，N表示序号,N=0..9 %N,引用最后一个RewriteCond模板中匹配的数据，N表示序号 %{VARNAME},服务器变量 ${mapname:key&#124;default},映射函数调用 这些特殊内容的扩展，按上述顺序进行。　　一个URL的全部相关部分都会被Substitution替换，而且这个替换过程会一直持续到所有的规则都被执行完，除非明确地用L标志中断处理过程。　　当susbstitution有&#8221;-&#8221;前缀时，表示不进行替换，只做匹配检查。　　利用RewriteRule，可定义含有请求串(Query String)的URL，此时只需在Sustitution中加入一个？，表示此后的内容放入QUERY_STRING变量中。如果要清空一个QUERY_STRING变量，只需要以？结束Substitution串即可。　　如果给一个Substitution增加一个http://thishost[:port]的前缀，则mod_rewrite会自动将此前缀去掉。因此，利用http://thisthost做一个无条件的重定向到自己，将难以奏效。要实现这种效果，必须使用R标志。　　Flags是可选参数，当有多个标志同时出现时，彼此间以逗号分隔。 &#8216;redirect&#124;R [=code]&#8216; (强制重定向)　　给当前的URI增加前缀http://thishost[:thisport]/， 从而生成一个新的URL，强制生成一个外部重定向(external redirection，指生的URL发送到客户端，由客户端再次以新的URL发出请求，虽然新URL仍指向当前的服务器). 如果没有指定的code值，则HTTP应答以状态值302 (MOVED TEMPORARILY)，如果想使用300-400（不含400）间的其它值可以通过在code的位置以相应的数字指定，也可以用标志名指定： temp (默认值), permanent, seeother.　　注意，当使用这个标志时，要确实substitution是个合法的URL，这个标志只是在URL前增加http://thishost[:thisport]/前缀而已，重写操作会继续进行。如果要立即将新URL重定向，用L标志来中重写流程。 &#8216;forbidden&#124;F&#8217; (强制禁止访问URL所指的资源)　　立即返回状态值403 (FORBIDDEN)的应答包。将这个标志与合适的RewriteConds 联合使用，可以阻断访问某些URL。 &#8216;gone&#124;G&#8217; (强制返回URL所指资源为不存在(gone))　　立即返回状态值410 (GONE)的应答包。用这个标志来标记URL所指的资源永久消失了. # &#8216;proxy&#124;P&#8217; (强制将当前URL送往代理模块（proxy module）)　　这个标志，强制将substitution当作一个发向代理模块的请求，并立即将共送往代理模块。因此，必须确保substitution串是一个合法的URI (如, 典型的情况是以http://hostname开头)，否则会从代理模块得到一个错误. 这个标志，是ProxyPass指令的一个更强劲的实现，将远程请求(remote stuff)映射到本地服务器的名字空间(namespace)中来。　　注意，使用这个功能必须确保代理模块已经编译到Apache 服务器程序中了. 可以用&#8220;httpd -l &#8221;命令，来检查输出中是否含有mod_proxy.c来确认一下。如果没有，而又需要使用这个功能，则需要重新编译&#8220;httpd&#8221;程序并使用mod_proxy有效。 &#8216;last&#124;L&#8217; (最后一条规则)　　中止重写流程，不再对当前URL施加更多的重写规则。这相当于perl的last命令或C的break命令。 &#8216;next&#124;N&#8217; (下一轮)　　重新从第一条重写规则开始执行重写过程，新开的过程中的URL不应当与最初的URL相同。 这相当于Perl的next命令或C的continue命令. 千万小心不要产生死循环。 # &#8216;chain&#124;C&#8217; (将当前的规则与其后续规则綑绑(chained))　　当规则匹配时，处理过程与没有綑绑一样；如果规则不匹配，则綑绑在一起的后续规则也不在检查和执行。 &#8216;type&#124;T=MIME-type&#8217; (强制MIME类型)　　强制将目标文件的MIME-type为某MIME类型。例如，这可用来模仿mod_alias模块对某目录的ScriptAlias指定，通过强制将该目录下的所有文件的类型改为 [...]]]></description>
			<content:encoded><![CDATA[<p>　今天学习重写规则的语法。<a name="more"></a></p>
<p><strong>RewriteRule</strong><br />Syntax: RewriteRule Pattern Substitution [flags] <br />　　一条RewriteRule指令，定义一条重写规则，规则间的顺序非常重要。对Apache1.2及以后的版本，模板(pattern)是一个POSIX正则式，用以匹配当前的URL。当前的URL不一定是用记最初提交的URL，因为可能用一些规则在此规则前已经对URL进行了处理。<br />　　对mod_rewrite来说，！是个合法的模板前缀，表示&ldquo;非&rdquo;的意思，这对描述&ldquo;不满足某种匹配条件&rdquo;的情况非常方便，或用作最后一条默认规则。当使用！时，不能在模板中有分组的通配符，也不能做后向引用。<br />　　当匹配成功后，Substitution会被用来替换相应的匹配，它除了可以是普通的字符串以外，还可以包括： </p>
<ol>
<li>$N,引用RewriteRule模板中匹配的相关字串，N表示序号,N=0..9 </li>
<li>%N,引用最后一个RewriteCond模板中匹配的数据，N表示序号 </li>
<li>%{VARNAME},服务器变量 </li>
<li>${mapname:key|default},映射函数调用 </li>
</ol>
<p>这些特殊内容的扩展，按上述顺序进行。<br />　　一个URL的全部相关部分都会被Substitution替换，而且这个替换过程会一直持续到所有的规则都被执行完，除非明确地用L标志中断处理过程。<br />　　当susbstitution有&rdquo;-&rdquo;前缀时，表示不进行替换，只做匹配检查。<br />　　利用RewriteRule，可定义含有请求串(Query String)的URL，此时只需在Sustitution中加入一个？，表示此后的内容放入QUERY_STRING变量中。如果要清空一个QUERY_STRING变量，只需要以？结束Substitution串即可。<br />　　如果给一个Substitution增加一个http://thishost[:port]的前缀，则mod_rewrite会自动将此前缀去掉。因此，利用http://thisthost做一个无条件的重定向到自己，将难以奏效。要实现这种效果，必须使用R标志。<br />　　Flags是可选参数，当有多个标志同时出现时，彼此间以逗号分隔。</p>
<ol>
<li>&#8216;redirect|R [=code]&#8216; (强制重定向)<br />　　给当前的URI增加前缀http://thishost[:thisport]/， 从而生成一个新的URL，强制生成一个外部重定向(external redirection，指生的URL发送到客户端，由客户端再次以新的URL发出请求，虽然新URL仍指向当前的服务器). 如果没有指定的code值，则HTTP应答以状态值302 (MOVED TEMPORARILY)，如果想使用300-400（不含400）间的其它值可以通过在code的位置以相应的数字指定，也可以用标志名指定： temp (默认值), permanent, seeother.<br />　　注意，当使用这个标志时，要确实substitution是个合法的URL，这个标志只是在URL前增加http://thishost[:thisport]/前缀而已，重写操作会继续进行。如果要立即将新URL重定向，用L标志来中重写流程。</li>
<li>&#8216;forbidden|F&#8217; (强制禁止访问URL所指的资源)<br />　　立即返回状态值403 (FORBIDDEN)的应答包。将这个标志与合适的RewriteConds 联合使用，可以阻断访问某些URL。</li>
<li>&#8216;gone|G&#8217; (强制返回URL所指资源为不存在(gone))<br />　　立即返回状态值410 (GONE)的应答包。用这个标志来标记URL所指的资源永久消失了.</li>
<li># &#8216;proxy|P&#8217; (强制将当前URL送往代理模块（proxy module）)<br />　　这个标志，强制将substitution当作一个发向代理模块的请求，并立即将共送往代理模块。因此，必须确保substitution串是一个合法的URI (如, 典型的情况是以http://hostname开头)，否则会从代理模块得到一个错误. 这个标志，是ProxyPass指令的一个更强劲的实现，将远程请求(remote stuff)映射到本地服务器的名字空间(namespace)中来。<br />　　注意，使用这个功能必须确保代理模块已经编译到Apache 服务器程序中了. 可以用&ldquo;httpd -l &rdquo;命令，来检查输出中是否含有mod_proxy.c来确认一下。如果没有，而又需要使用这个功能，则需要重新编译&#8220;httpd&#8221;程序并使用mod_proxy有效。</li>
<li>&#8216;last|L&#8217; (最后一条规则)<br />　　中止重写流程，不再对当前URL施加更多的重写规则。这相当于perl的last命令或C的break命令。</li>
<li>&#8216;next|N&#8217; (下一轮)<br />　　重新从第一条重写规则开始执行重写过程，新开的过程中的URL不应当与最初的URL相同。 这相当于Perl的next命令或C的continue命令. 千万小心不要产生死循环。</li>
<li># &#8216;chain|C&#8217; (将当前的规则与其后续规则綑绑(chained))<br />　　当规则匹配时，处理过程与没有綑绑一样；如果规则不匹配，则綑绑在一起的后续规则也不在检查和执行。</li>
<li>&#8216;type|T=MIME-type&#8217; (强制MIME类型)<br />　　强制将目标文件的MIME-type为某MIME类型。例如，这可用来模仿mod_alias模块对某目录的ScriptAlias指定，通过强制将该目录下的所有文件的类型改为 &ldquo;application/x-httpd-cgi&rdquo;.</li>
<li>&#8216;nosubreq|NS&#8217; (used only if no internal sub-request )<br />　　这个标志强制重写引擎跳过为内部sub-request的重写规则.例如，当mod_include试图找到某一目录下的默认文件时 (index.xxx)，sub-requests 会在Apache内部发生. Sub-requests并非总是有用的，在某些情况下如果整个规则集施加到它上面，会产生错误。利用这个标志可排除执行一些规则。</li>
<li>&#8216;nocase|NC&#8217; (模板不区分大小写)<br />　　这个标志会使得模板匹配当前URL时忽略大小写的差别。</li>
<li>&#8216;qsappend|QSA&#8217; (追加请求串(query string))<br />　　这个标志，强制重写引擎为Substitution的请求串追加一部分串，则不是替换掉原来的。借助这个标志，可以使用一个重写规则给请求串增加更多的数据。</li>
<li>&#8216;noescape|NE&#8217; (不对输出结果中的特殊字符进行转义处理)<br />　　通常情况下，mod_write的输出结果中，特殊字符（如&#8217;%', &#8216;$&#8217;, &#8216;;&#8217;, 等)会转义为它们的16进制形式(如分别为&#8217;%25&#8242;, &#8216;%24&#8242;, and &#8216;%3B&#8217;）。这个标志会禁止mod_rewrite对输出结果进行此类操作。 这个标志只能在 Apache 1.3.20及以后的版本中使用。</li>
<li>&#8216;passthrough|PT&#8217; (通过下一个处理器)<br />　　这个标志强制重写引擎用filename字段的值来替换内部request_rec数据结构中uri字段的值。. 使用这个标志，可以使后续的其它URI－to-filename转换器的Alias、ScriptAlias、Redirect等指令，也能正常处理RewriteRule指令的输出结果。用一个小例子来说明它的语义：如果要用mod_rewrite的重写引擎将/abc转换为/def,然后用mod_alas将/def重写为ghi，则要：<br />RewriteRule ^/abc(.*) /def$1 [PT]<br />Alias /def /ghi<br />如果PT标志被忽略，则mod_rewrite也能很好完成工作,如果., 将 uri=/abc/&#8230; 转换为filename=/def/&#8230; ，完全符合一个URI-to-filename转换器的动作。接下来 mod_alias 试图做 URI-to-filename 转换时就会出问题。<br />注意:如果要混合都含有URL－to-filename转换器的不同的模块的指令，必须用这个标志。最典型的例子是mod_alias和mod_rewrite的使用。 </li>
<li>&#8216;skip|S=num&#8217; (跳过后面的num个规则)<br />　　当前规则匹配时，强制重写引擎跳过后续的num个规则。用这个可以来模仿if-then-else结构：then子句的最后一条rule的标志是skip=N，而N是else子句的规则条数。</li>
<li>&#8216;env|E=VAR:VAL&#8217; (设置环境变量)<br />　　设置名为VAR的环境变量的值为VAL,其中VAL中可以含有正则式的后向引用($N或%N)。这个标志可以使用多次，以设置多个环境变量。这儿设置的变量，可以在多种情况下被引用，如在XSSI或CGI中。另外，也可以在RewriteCond模板中以%{ENV:VAR}的形式被引用。</li>
<li>&nbsp;</li>
</ol>
<p>注意：一定不要忘记，在服务器范围内的配置文件中，模板(pattern)用以匹配整个URL;而在目录范围内的配置文件中，目录前缀总是被自动去掉后再进行模板匹配的，且在替换完成后自动再加上这个前缀。这个功能对很多种类的重写是非常重要的，因为如果没有去前缀，则要进行父目录的匹配，而父目录的信息并不是总能得到的。一个例外是，当substitution中有http://打头时，则不再自动增加前缀了，如果P标志出现，则会强制转向代理。<br />注意：如果要在某个目录范围内启动重写引擎，则需要在相应的目录配置文件中设置&ldquo;RewriteEngine on&rdquo;，且目录的&ldquo;Options FollowSymLinks&rdquo;必须设置。如果管理员由于安全原因没有打开FollowSymLinks，则不能使用重写引擎。</p>
<div id="crp_related"><h3>Related Posts:</h3><ul><li><a href="http://observerlife.com/apache%e7%9a%84mod_rewrite%e5%ad%a6%e4%b9%a0%ef%bc%88%e4%b8%80%ef%bc%89/" rel="bookmark" class="crp_title">Apache的Mod_rewrite学习（一）</a></li><li><a href="http://observerlife.com/e50%e7%9a%84%e5%90%8d%e7%89%87%e5%a4%b9%e6%98%af%e5%a6%82%e4%bd%95%e6%8e%92%e5%88%97%e7%9a%84%e7%bb%9d/" rel="bookmark" class="crp_title">E50的名片夹是如何排列的?绝!!</a></li><li><a href="http://observerlife.com/%e4%bc%81%e4%b8%9a%e6%bf%80%e5%8a%b1%e4%ba%ba%e6%89%8d%e6%9c%80%e5%ae%9e%e7%94%a8%e7%9a%84%e4%b8%83%e7%a7%8d%e6%96%b9%e6%b3%95/" rel="bookmark" class="crp_title">企业激励人才最实用的七种方法</a></li><li><a href="http://observerlife.com/%e3%80%8a%e5%a3%ab%e5%85%b5%e7%aa%81%e5%87%bb%e3%80%8b-%e6%af%8f%e4%b8%aa%e4%ba%ba%e7%9a%84%e5%bf%83%e7%81%b5%e5%8f%b2%ef%bc%88%e7%ac%ac%e4%b8%89%e8%8a%82%ef%bc%89/" rel="bookmark" class="crp_title">《士兵突击》- 每个人的心灵史（第三节）</a></li><li><a href="http://observerlife.com/%e3%80%8a%e5%a3%ab%e5%85%b5%e7%aa%81%e5%87%bb%e3%80%8b-%e6%af%8f%e4%b8%aa%e4%ba%ba%e7%9a%84%e5%bf%83%e7%81%b5%e5%8f%b2%ef%bc%88%e7%ac%ac%e4%ba%8c%e8%8a%82%ef%bc%89/" rel="bookmark" class="crp_title">《士兵突击》- 每个人的心灵史（第二节）</a></li></ul></div>]]></content:encoded>
			<wfw:commentRss>http://observerlife.com/apache%e7%9a%84mod_rewrite%e5%ad%a6%e4%b9%a0%ef%bc%88%e4%ba%8c%ef%bc%89/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Apache的Mod_rewrite学习（一）</title>
		<link>http://observerlife.com/apache%e7%9a%84mod_rewrite%e5%ad%a6%e4%b9%a0%ef%bc%88%e4%b8%80%ef%bc%89/</link>
		<comments>http://observerlife.com/apache%e7%9a%84mod_rewrite%e5%ad%a6%e4%b9%a0%ef%bc%88%e4%b8%80%ef%bc%89/#comments</comments>
		<pubDate>Wed, 11 Apr 2007 07:23:22 +0000</pubDate>
		<dc:creator>ycg</dc:creator>
				<category><![CDATA[Unix/Linux]]></category>
		<category><![CDATA[apache]]></category>
		<category><![CDATA[mod_rewrite]]></category>

		<guid isPermaLink="false">http://www.kedy.cn/blog/?p=146</guid>
		<description><![CDATA[　　车东很早就写了一篇文章来介绍利用mod_rewrite模块来达到用静态页面形式的链接隐藏后台的动态页面。　　Apache的rewrite模块，提供了一个基于规则的重写(rewrite,也许译为重构更为合适)引擎，来实时重写发送到Apache的请求URL。因功能极其强大，被称为URL重写的&#8220;瑞士军刀&#8221;。 　　这个模块使用一个基于正则表达式解析器开发的重写引擎，根据web管理员定义的规则来实时(on the fly)重写请求URL。它支持任意数目的重写规则，以及附加到一条规则上的任意数目的规则条件，从而提供了一套非常灵活和功能强大的URL处理机制。URL处理操作的实施与否，依赖于各种各样的条件检查，如检查服务器变量、环境变量、HTTP头字段、时间戳的值，甚至外部数据库的检索结果。这个模块可以在服务器范围内(http.conf)、目录范围内(.htaccess)或请求串(query-string)的一部分处理有关的URL。重写的结果URL，可以指向一个站内的处理程序、指向站外的重定向或者一个站内的代理。与灵活和功能强大相随的是设置的复杂，别指望一天内弄明白整个模块。(所以，这个学习笔记也分了几部分：)　　 内部处理过程 API阶段　　首先，Apache处理HTTP请求是分阶段进行的,Apache API为每个阶段提供了一个钩子(hook)。Mod_rewrite使用了其中的两个钩子：一个用来在HTTP请求被读取但还没有访问授权验证之前进行URL_to_filename转换，一个用来在授权验证完成且目录设置文件(.htaccess)读取之后、但内容处理器(content handler)被调用之前激化，进行修补(fixup).因此，当一个请求到达，Apache决定了相关的服务器（或虚拟服务器）以后进行URL_to_filename阶段，重写引擎(rewrite engine)开始处理服务器设置中的重写指令(mod_rewrite directives).接下来几个阶段过后进入修补阶段，此时最终的数据所在的物理目录已经找到，目录配置中的重写指令开始执行。在这两个阶段，mod_rewrite都是将URL重写为新的URL或文件名，所以看起来并没有明显的区别。对API的这种应用，并不是一开始就是这样设计的，而是Apache1.x不得已而为之。为了搞清这个问题，以下两点需要记住。　　1)虽然mod_rewrite能进行URL到URL、URL到文件名字甚至文件名字到文件名字的转换，API(1.x)目前提供了一个URL_to_filename转换。在Apache2.0中，这两个钩子会被加进去，整个过程会更加清晰。一个事实必须清楚的记得：Apache在URL_to_filename钩子中，做得比API设计的功能更多。　　2)不可思议的是，mod_rewrite能在目录范围内（如根据.htaccess文件的指令配置）进行URL处理，虽然URL很早就已经被转换为文件名字了。只所以会如此，是因为.htaccess文件存在于文件系统中。也就是说，在这个阶段来进行URL处理，是非常晚的时候了。为了解决这个&#34;先有鸡还是先有蛋&#34;的问题，mod_rewrite用了一个小技巧：当在目录范围内处理URL/filename时，mod_rewrite先将文件名逆转回相关的URL(虽然通常是不可能的，但请参见下面用以实现这个技巧的RewriteBase指令)，然后据这个新URL生成一个站内的子请求(internal sub-request)，这又重开始了API进程。Mod_rewrite尽量使这些复杂的步骤对用户透明，但应要记住：虽然目录范围URL的真正处理过程很快很高效，但这一阶段会因为这个&#34;鸡和蛋&#34;的问题而变得很慢和低效。从另一方面来看，这也是mod_rewrite提供给普通用户进行目录范围内的URL处理的唯一途径.规则集(RewriteRule指令集合)处理过程　　当mod_rewrite在上述的两个API阶段被激活时，它会从它的配置数据结构（在开始服务器上下文(per-server context)或目录上下文(per-directory context)时创建的）中读取配置的规则集，然后URL重写引擎启动来执行包含的规则集（一个或多条规则以及它们的条件）。两种上下文中的处理过程都是一样的，差别只是在最后的结果处理过程上。　　规则集中规则的顺序是非常重要的，因为重写引擎以特定的顺序来处理它们。重写引擎顺序遍历规则集，当一条规则匹配时，引擎会去遍历与它相关的条件集(RewriteCond指令集合).由于历史的原因，条件集先被列出来，因此控制流流程有点曲折(long-winded).如图一所示：　　正如所看到的，首先URL会与每条规则的模板(pattern)比较，当匹配失败时，立即停止对当前规则的处理进入下一条规则。当匹配成功时，mod_rewrite寻找相关的规则条件。如果找不到相关的条件，则直接执行规则中定义的替换，然后回到规则遍历的过程。如果找到了相关的条件，则启动一个内部循环，依次检查各个条件。对于检查，我们不是拿一个模板来匹配当前的URL，而是先创建一个TestString串，将串内的变量、后向引用(bakc-reference)、查询结果(map lookups)等展开，然后用这个TestString和条件式中的CondPattern进行匹配，如果匹配失败，则整个条件集且这个规则都不再执行，重要回到规则遍历中；如果匹配成功，则检查下一个条件，如果所有的条件都满足，则执行规则中定义的替换动作。　　特殊字符的转义　　既然基于正则式，则当然会有特殊字符的问题。在1.3.20版本的Apache中，通过在特殊字符前加一个&#8220;&#8221;来将TestString或Sustitution串的特殊字符转义。正则式的后向引用　　有一点需要记住：一旦在模板(pattern)或条件模板(CondPattern)中使用了括号，则后向引用已经自动产生了，你可以在Sustitution或TestString中通过$N或%N来引用相关的值。如图，描述了后向引用的值可以传到的位置。 配置指令(Configuration Directives) 指令 语法 默认值 说明 备注 RewriteEngine RewriteEngine on&#124;off Off 开关重构引擎 默认时不能继承，故每个虚拟主机都要有自己的开关指令。 RewriteOptions RewriteOptions Option MaxRedirects=10 设置一些特殊参数 inherit:配置是否继承，MaxRedirects=number:内部重定向次数 RewriteLog RewriteLog file-path None 设定重写log文件 用RewriteLogLevel 0来禁止日志 RewriteLogLevel RewriteLogLevel Level RewriteLogLevel 0 设置日志级别 0表示没有，2以上用于debug，9及以上表示全部信息 RewriteLock RewriteLock file-path None 设置RewriteMap程序的同步锁文件 要求是本地文件，此文件只对rewriting map-program有效。 RewriteMap [...]]]></description>
			<content:encoded><![CDATA[<table style="table-layout: fixed;">
<tbody>
<tr>
<td>
<div class="cnt">
<p><img width="500" height="62" border="0" align="left" alt="apachelogo.gif" src="http://hedong.3322.org/archives/pics/apachelogo.gif" />　　<a href="http://www.chedong.com/">车东</a>很早就写了一篇文章来介绍<a title="面向Google(Search Engine Friendly)的URL设计 " href="http://www.chedong.com/tech/google_url.html">利用mod_rewrite模块来达到用静态页面形式的链接隐藏后台的动态页面</a>。<br />　　Apache的rewrite模块，提供了一个基于规则的重写(rewrite,也许译为重构更为合适)引擎，来实时重写发送到Apache的请求URL。因功能极其强大，被称为URL重写的&ldquo;瑞士军刀&rdquo;。</p>
<p>            <a name="more"></a></p>
<p>　　这个模块使用一个基于正则表达式解析器开发的重写引擎，根据web管理员定义的规则来实时(on the fly)重写请求URL。它支持任意数目的重写规则，以及附加到一条规则上的任意数目的规则条件，从而提供了一套非常灵活和功能强大的URL处理机制。URL处理操作的实施与否，依赖于各种各样的条件检查，如检查服务器变量、环境变量、HTTP头字段、时间戳的值，甚至外部数据库的检索结果。这个模块可以在服务器范围内(http.conf)、目录范围内(.htaccess)或请求串(query-string)的一部分处理有关的URL。重写的结果URL，可以指向一个站内的处理程序、指向站外的重定向或者一个站内的代理。与灵活和功能强大相随的是设置的复杂，别指望一天内弄明白整个模块。(所以，这个学习笔记也分了几部分：)<br />　　 </p>
<h4>内部处理过程</h4>
<p>            <strong>API阶段</strong><br />　　首先，Apache处理HTTP请求是分阶段进行的,Apache API为每个阶段提供了一个钩子(hook)。Mod_rewrite使用了其中的两个钩子：一个用来在HTTP请求被读取但还没有访问授权验证之前进行URL_to_filename转换，一个用来在授权验证完成且目录设置文件(.htaccess)读取之后、但内容处理器(content handler)被调用之前激化，进行修补(fixup).因此，当一个请求到达，Apache决定了相关的服务器（或虚拟服务器）以后进行URL_to_filename阶段，重写引擎(rewrite engine)开始处理服务器设置中的重写指令(mod_rewrite directives).接下来几个阶段过后进入修补阶段，此时最终的数据所在的物理目录已经找到，目录配置中的重写指令开始执行。在这两个阶段，mod_rewrite都是将URL重写为新的URL或文件名，所以看起来并没有明显的区别。对API的这种应用，并不是一开始就是这样设计的，而是Apache1.x不得已而为之。为了搞清这个问题，以下两点需要记住。<br />　　1)虽然mod_rewrite能进行URL到URL、URL到文件名字甚至文件名字到文件名字的转换，API(1.x)目前提供了一个URL_to_filename转换。在Apache2.0中，这两个钩子会被加进去，整个过程会更加清晰。一个事实必须清楚的记得：Apache在URL_to_filename钩子中，做得比API设计的功能更多。<br />　　2)不可思议的是，mod_rewrite能在目录范围内（如根据.htaccess文件的指令配置）进行URL处理，虽然URL很早就已经被转换为文件名字了。只所以会如此，是因为.htaccess文件存在于文件系统中。也就是说，在这个阶段来进行URL处理，是非常晚的时候了。为了解决这个&quot;先有鸡还是先有蛋&quot;的问题，mod_rewrite用了一个小技巧：当在目<ins>录</ins>范围内处理URL/filename时，mod_rewrite先将文件名逆转回相关的URL(虽然通常是不可能的，但请参见下面用以实现这个技巧的RewriteBase指令)，然后据这个新URL生成一个站内的子请求(internal sub-request)，这又重开始了API进程。Mod_rewrite尽量使这些复杂的步骤对用户透明，但应要记住：虽然目录范围URL的真正处理过程很快很高效，但这一阶段会因为这个&quot;鸡和蛋&quot;的问题而变得很慢和低效。从另一方面来看，这也是mod_rewrite提供给普通用户进行目录范围内的URL处理的唯一途径.<br /><strong>规则集(RewriteRule指令集合)处理过程</strong><br />　　当mod_rewrite在上述的两个API阶段被激活时，它会从它的配置数据结构（在开始服务器上下文(per-server context)或目录上下文(per-directory context)时创建的）中读取配置的规则集，然后URL重写引擎启动来执行包含的规则集（一个或多条规则以及它们的条件）。两种上下文中的处理过程都是一样的，差别只是在最后的结果处理过程上。<br />　　规则集中规则的顺序是非常重要的，因为重写引擎以特定的顺序来处理它们。重写引擎顺序遍历规则集，当一条规则匹配时，引擎会去遍历与它相关的条件集(RewriteCond指令集合).由于历史的原因，条件集先被列出来，因此控制流流程有点曲折(long-winded).如图一所示：<img width="428" height="385" border="0" align="right" alt="mod_rewrite_fig1.gif" src="http://hedong.3322.org/archives/pics/mod_rewrite_fig1.gif" /><br />　　正如所看到的，首先URL会与每条规则的模板(pattern)比较，当匹配失败时，立即停止对当前规则的处理进入下一条规则。当匹配成功时，mod_rewrite寻找相关的规则条件。如果找不到相关的条件，则直接执行规则中定义的替换，然后回到规则遍历的过程。如果找到了相关的条件，则启动一个内部循环，依次检查各个条件。对于检查，我们不是拿一个模板来匹配当前的URL，而是先创建一个TestString串，将串内的变量、后向引用(bakc-reference)、查询结果(map lookups)等展开，然后用这个TestString和条件式中的CondPattern进行匹配，如果匹配失败，则整个条件集且这个规则都不再执行，重要回到规则遍历中；如果匹配成功，则检查下一个条件，如果所有的条件都满足，则执行规则中定义的替换动作。　　<br /><strong>特殊字符的转义</strong><br />　　既然基于正则式，则当然会有特殊字符的问题。在1.3.20版本的Apache中，通过在特殊字符前加一个&ldquo;&rdquo;来将TestString或Sustitution串的特殊字符转义。<br /><strong>正则式的后向引用</strong><br /><img width="381" height="179" border="0" align="left" alt="mod_rewrite_fig2.gif" src="http://hedong.3322.org/archives/pics/mod_rewrite_fig2.gif" />　　有一点需要记住：一旦在模板(pattern)或条件模板(CondPattern)中使用了括号，则后向引用已经自动产生了，你可以在Sustitution或TestString中通过$N或%N来引用相关的值。如图，描述了后向引用的值可以传到的位置。</p></div>
</td>
</tr>
</tbody>
</table>
<h4>配置指令(Configuration Directives)</h4>
<table border="1" style="width: 624px; height: 704px;">
<tbody>
<tr>
<td>指令</td>
<td>语法</td>
<td>默认值</td>
<td>说明</td>
<td>备注</td>
</tr>
<tr>
<td>RewriteEngine</td>
<td>RewriteEngine on|off</td>
<td>Off</td>
<td>开关重构引擎</td>
<td>默认时不能继承，故每个虚拟主机都要有自己的开关指令。</td>
</tr>
<tr>
<td>RewriteOptions</td>
<td>RewriteOptions Option</td>
<td>MaxRedirects=10</td>
<td>设置一些特殊参数</td>
<td>inherit:配置是否继承，MaxRedirects=number:内部重定向次数</td>
</tr>
<tr>
<td>RewriteLog</td>
<td>RewriteLog file-path</td>
<td>None</td>
<td>设定重写log文件</td>
<td>用RewriteLogLevel 0来禁止日志</td>
</tr>
<tr>
<td>RewriteLogLevel</td>
<td>RewriteLogLevel Level</td>
<td>RewriteLogLevel 0</td>
<td>设置日志级别</td>
<td>0表示没有，2以上用于debug，9及以上表示全部信息</td>
</tr>
<tr>
<td>RewriteLock</td>
<td>RewriteLock file-path</td>
<td>None</td>
<td>设置RewriteMap程序的同步锁文件</td>
<td>要求是本地文件，此文件只对rewriting map-program有效。</td>
</tr>
<tr>
<td>RewriteMap</td>
<td>RewriteMap MapName MapType:MapSource</td>
<td>Notused per default</td>
<td>定义重写影射</td>
<td>具体说明参见<a href="http://hedong.3322.org/archives/000346.html">文档</a></td>
</tr>
<tr>
<td>RewriteBase</td>
<td>RewriteBase URL-path</td>
<td>physical directory path</td>
<td>设置目录范围内重写的基本URL</td>
<td>具体说明参见<a href="http://hedong.3322.org/archives/000346.html">文档</a></td>
</tr>
<tr>
<td>RewriteCond</td>
<td>RewriteCond TestString CondPattern</td>
<td>None</td>
<td>定义规则条件</td>
<td>具体说明参见<a href="http://hedong.3322.org/archives/000345.html">文档</a></td>
</tr>
<tr>
<td>RewriteRule</td>
<td>RewriteRule Pattern Substitution</td>
<td>None</td>
<td>定义重写规则</td>
<td>具体说明参见<a href="http://hedong.3322.org/archives/000344.html">文档</a></td>
</tr>
</tbody>
</table>
<p>参考资料：<br />http://httpd.apache.org/docs/mod/mod_rewrite.html</p>
<div id="crp_related"><h3>Related Posts:</h3><ul><li><a href="http://observerlife.com/%e6%8a%80%e5%b7%a7-%e4%bd%bf%e7%94%a8truss%e3%80%81strace%e6%88%96ltrace%e8%af%8a%e6%96%ad%e8%bd%af%e4%bb%b6%e7%9a%84%e7%96%91%e9%9a%be%e6%9d%82%e7%97%87/" rel="bookmark" class="crp_title">技巧: 使用truss、strace或ltrace诊断软件的&quot;疑难杂症&quot;</a></li><li><a href="http://observerlife.com/freebsd7%e5%ae%89%e8%a3%85%e6%89%8b%e5%86%8c-%e6%9b%b4%e6%96%b0ports-%e5%92%8csrc/" rel="bookmark" class="crp_title">freebsd7安装手册-更新ports 和src</a></li><li><a href="http://observerlife.com/lighttpdsquidapache%e6%90%ad%e5%bb%ba%e9%ab%98%e6%95%88%e7%8e%87web%e6%9c%8d%e5%8a%a1%e5%99%a8/" rel="bookmark" class="crp_title">Lighttpd+Squid+Apache搭建高效率Web服务器</a></li><li><a href="http://observerlife.com/%e7%ae%80%e5%8d%95%e6%a3%80%e6%b5%8b%e6%93%8d%e4%bd%9c%e7%b3%bb%e7%bb%9f%e6%98%af%e5%90%a6%e6%98%af64%e4%bd%8d%e7%b3%bb%e7%bb%9f%e7%9a%84%e6%96%b9%e6%b3%95php%e7%89%88/" rel="bookmark" class="crp_title">简单检测操作系统是否是64位系统的方法php版</a></li><li><a href="http://observerlife.com/%e5%85%b3%e4%ba%8eapache%e7%9a%84timeout/" rel="bookmark" class="crp_title">关于Apache的TimeOut</a></li></ul></div>]]></content:encoded>
			<wfw:commentRss>http://observerlife.com/apache%e7%9a%84mod_rewrite%e5%ad%a6%e4%b9%a0%ef%bc%88%e4%b8%80%ef%bc%89/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
