2011-06-14 73 views
7

我有以下网址...怎样才能mod_rewrite的匹配规则只有一次

http://localhost/http.mygarble.com/foundationsofwebprogramming/86

...我想转换成以下:

http://localhost/http.mygarble.com/php/blog.php?subdomain=foundationsofwebprogramming&page=posts&label=86

我想我可以用下面的规则做到这一点:

RewriteRule ([^/]+)/([^/]+)$ php/blog.php?subdomain=$1&page=post&label=$2 [NC,L] 

但是我发现这个规则被反复应用,导致内部服务器错误。我明白,当使用此规则转换URI时,生成的URI也将匹配规则,因此它将再次应用ad-infinitum。

我以前的(当然是非常模糊的)理解是,[L]标志会停止进一步的处理,但我现在明白,这只是意味着只有其余规则被跳过,并且不会停止重写引擎的运行再次通过规则。

我可以通过添加以下条件解决这个问题...

RewriteCond $0 !php/blog.php 
RewriteRule ([^/]+)/([^/]+)$ php/blog.php?subdomain=$1&page=post&label=$2 [NC,L] 

...或者写一个更具体的正则表达式。但是我真正想要做的是找到一种方法,一旦这个规则匹配一次,就停止尝试任何进一步匹配的重写引擎。这可能吗?

非常感谢。

回答

16

通常使用2种方法。

第一个是Rewrite Condition测试,请求的文件不是真实文件。当内部递归出现时,你的php/blog.php是一个真正的文件,并且第二次执行rewriterule。副作用是,它存在不会被改写为文件的任何请求(可以是很好的副作用)

RewriteCond %{REQUEST_FILENAME} !-f 

第二个解决方案是检查与内部重定向不是:

RewriteCond %{ENV:REDIRECT_STATUS} ^$ 

这个第二个解决方案的副作用是,如果之前应用了其他某些规则(如果您希望在第一次重写实际执行后运行一些内部重定向),则不能应用rewriteRule。

编辑

完成,我将增加第三法:[NS]或[nosubreq]标签似乎是在做同样的事情。内部重定向后防止规则使用。

+0

第二个解决方案是理想的。我想要的唯一重定向是外部的,所有规则都只能运行一次。谢谢。 – 2011-06-14 14:14:46

+0

不幸的是,我没有声望投票答复你的答案,也许有人会代表我做。再次感谢。 – 2011-06-14 14:15:51

+0

@詹姆斯史密斯:你不需要提高我的答案,你应该“接受”它(这样我就得到了绿色标记)。 – regilero 2011-06-14 14:28:58

4

第三种方法是将apache升级到2.3.9或更高版本,并使用[END]标志而不是[L]。

没有副作用

相关问题