多个重写条件:如何在一组规则之前链接它们?
Posted
技术标签:
【中文标题】多个重写条件:如何在一组规则之前链接它们?【英文标题】:Multiple RewriteConditions: How to chain them before a set of rules? 【发布时间】:2011-07-15 10:15:42 【问题描述】:Q1:如何将这两个条件链接起来使它们if BOTH A AND B, then proceed...
Q2:如何使它们坚持所有重写下面的规则,而不仅仅是第一条规则?
RewriteCond %REQUEST_URI ^IMAGE-.*$ // if filename starts with IMG- and,
RewriteCond %REQUEST_FILENAME !-f // if file does exist, then proceed:
RewriteRule Rule1
RewriteRule Rule2
RewriteRule Rule3
# -- END IF -- STOP HERE -- #
【问题讨论】:
你能把[L]
标志放在最后一个吗?没有测试过,只是凭记忆思考...
【参考方案1】:
Q1:默认为 AND。
Q2:它们只会影响下面的 RewriteRule。
【讨论】:
+1 谢谢!正如亚历克斯在我的问题中评论的那样,添加 [L] 标志有什么不同吗? L 标志与您的问题无关。【参考方案2】:你不能那样做。您必须重复您的 RewriteConds 或使用引用重新考虑您的重写规则,以便在一条规则中完成所有操作。第一条路线虽然不漂亮,但会是最简单的。所以
RewriteCond A
RewriteCond B
RewriteRule 1
RewriteCond A #duplicate
RewriteCond B #duplicate
RewriteRule 2
【讨论】:
@user @alex 对我的问题的评论如何,他说要在最后一个上添加 [L]? @Sam [L] 仅表示“对于此请求,请不要再执行这些规则。不适用于您的情况。更适合您说的情况:如果 URL 像 / blah/foo 然后做 A [L] 如果 URL 像 /blah 然后做 B。[L] 说停在这里,即使它符合第二个条件也不做 B。希望这是有道理的 :) @ChuckKollars 我也想到了[C]
,但这取决于RewriteRule
s 是什么。有时RewriteCond
s 是唯一真实的条件,RewriteRule
s 总是匹配的(例如RewriteRule ^ - [E=foo:42]
)。在规则总是匹配的情况下,[C]
是要走的路。另一方面,如果您的 RewriteRule
s 有可能不匹配的条件,您将在第一个不匹配的规则处停止处理 [C]
s,这可能不是 OP 想要的。
@ChuckKollars RewriteRule
的语法是RewriteRule pattern subst [flags]
,对吧?例如,如果您有三个 RewriteRule
s 和不同的 pattern
s,并且您使用 [C]
将它们链接在一起,那么第一个不匹配的 pattern
将终止链:任何以下链式规则将不跑。我对 OP 的解读是,他们希望三个RewriteRule
s 都取决于前面的RewriteCond
s,我只是指出[C]
是在这种情况下使用的东西只要 保证所有规则的pattern
s 匹配。
@dale 我忘记了在我相当不寻常的环境中工作的东西通常不能正常工作。感谢您指出了这一点!我删除了我的 cmets,因为它们反映的环境比 OP 询问的更专业。【参考方案3】:
这里有一些技巧可以让RewriteCond
堆栈适用于多个RewriteRule
,按递增WTF's per minute 排序。但这是配置而不是代码,所以这些规则不适用,对吧? :-)
1。环境变量
当您有许多 RewriteCond
时,将它们的结果存储在环境变量中,然后在每个规则中进行测试会更加紧凑。
# Your RewriteCond stack.
RewriteCond %REQUEST_URI !^IMAGE-.*$ [OR]
RewriteCond %REQUEST_FILENAME -f
# Store environment variable.
RewriteRule ^ - [E=TRUE:YEP]
# Assert environment variable in remaining RewriteRule's.
RewriteCond %ENV:TRUE =YEP
RewriteRule Rule1
RewriteCond %ENV:TRUE =YEP
RewriteRule Rule2
RewriteCond %ENV:TRUE =YEP
RewriteRule Rule3
2。跳过标志
这个有点微妙。使用[S]
或[skip]
标志,您可以跳过整个RewriteRule
块。
# Your RewriteCond stack.
RewriteCond %REQUEST_URI !^IMAGE-.*$ [OR]
RewriteCond %REQUEST_FILENAME -f
# If RewriteCond's match, skip the next RewriteRule.
RewriteRule ^ - [skip=1]
# Otherwise, this rule will match and the rest will be skipped.
RewriteRule ^ - [skip=3]
RewriteRule Rule1
RewriteRule Rule2
RewriteRule Rule3
这有点像 if 语句,RewriteCond
是条件,RewriteRule
是代码块。
您获得的重复更少,但代价是代码不太清晰,每次您从这组 N RewriteRule
' 中添加或删除规则时都必须更新 [skip=N]
秒。
好吧,如果你还在阅读,在这里你会发现另外两个解决方案,WTF's per minute 达到并超过临界点。它们仅供娱乐,您会明白为什么。
3。跳过没有 N 的标志
是的,有一种方法可以使用[skip]
标志而不包括N,即您要应用RewriteCond
堆栈的RewriteRule
的数量。也就是说...如果您在每个 RewriteRule
之前添加一对 RewriteCond
,哦,是的,最后还有一个。
# Your RewriteCond stack.
RewriteCond %REQUEST_URI !^IMAGE-.*$ [OR]
RewriteCond %REQUEST_FILENAME -f
# If RewriteCond's match, skip the next RewriteRule.
RewriteRule ^ - [skip=1] # succeeded
RewriteRule ^ - [skip=2] # failed
RewriteRule Rule1
RewriteRule ^ - [skip=1] # succeeded
RewriteRule ^ - [skip=2] # failed
RewriteRule Rule2
RewriteRule ^ - [skip=1] # succeeded
RewriteRule ^ - [skip=2] # failed
RewriteRule Rule3
RewriteRule ^ - # no-op to cover for last [skip=2] rule
这里的诀窍是,当且仅当RewriteCond
成功时,每个[skip=1]
规则都会被处理,而当且仅当它们失败时,每个[skip=2]
规则才会被处理。
4。网址标记
使用部分 URL 来保持状态,然后在您的 RewriteRule
中匹配它。
# Your RewriteCond stack.
RewriteCond %REQUEST_URI !^IMAGE-.*$ [OR]
RewriteCond %REQUEST_FILENAME -f
# If RewriteCond's match, prepend bogus marker "M#" to internal URL.
RewriteRule .* M#$0
# All your RewriteRule's test for this marker plus whatever else.
RewriteRule ^M#.*Rule1
RewriteRule ^M#.*Rule2
RewriteRule ^M#.*Rule3
# Finally, don't forget to strip off the bogus marker.
RewriteRule ^M#(.*) $1
带有标记的新 URL 无效,但最后一个 RewriteRule
还原它,对吗?好吧,只有当它被处理时,所以不要让标记 URL 在它被还原之前逃脱这一轮 mod_rewrite 处理。然后你会得到一个 404。
【讨论】:
我不得不在办公室大声笑,感谢sorted by increasing WTF's per minute
。以前从未听说过以上是关于多个重写条件:如何在一组规则之前链接它们?的主要内容,如果未能解决你的问题,请参考以下文章