如何让mod_rewrite只匹配一次规则

时间:2011-06-14 10:36:32

标签: apache 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也会匹配规则,因此会无限制地再次应用。

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

我可以通过添加以下条件来解决此问题...

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

...或者通过编写更具体的正则表达式。但我真正想做的是找到一种方法来阻止重写引擎在匹配一次此规则后尝试任何进一步的匹配。这可能吗?

非常感谢。

2 个答案:

答案 0 :(得分:16)

通常使用2种方法。

第一个是重写条件测试,请求的文件不是真实文件。当内部递归出现时,你的php / blog.php是一个真正的文件,并且第二次不执行重写。副作用是对任何存在的文件的请求都不会被重写(这可能是好的副作用)

RewriteCond %{REQUEST_FILENAME} !-f

第二个解决方案是检查您是否处于内部重定向:

RewriteCond %{ENV:REDIRECT_STATUS} ^$

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

<击> 修改

<击>

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

答案 1 :(得分:4)

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

无副作用