如何在 Apache 上对 RewriteCond 使用“AND”、“OR”?
Posted
技术标签:
【中文标题】如何在 Apache 上对 RewriteCond 使用“AND”、“OR”?【英文标题】:how to use "AND", "OR" for RewriteCond on Apache? 【发布时间】:2010-10-29 16:10:43 【问题描述】:这是如何在 Apache 上对RewriteCond
使用 AND 或 OR?
rewritecond A [or]
rewritecond B
rewritecond C [or]
rewritecond D
RewriteRule ... something
变成if ( (A or B) and (C or D) ) rewrite_it
。
所以看起来“OR”的优先级高于“AND”?有没有办法很容易分辨,比如(A or B) and (C or D)
语法?
【问题讨论】:
是的,正确的。 [OR] 的优先级高于(隐式)“AND”。组合条件确实是 ((A or B) and (C or D))。 您可以在ckollars.org/apache-rewrite-htaccess.html#precedence 中找到有用的详细信息。 【参考方案1】:经过多次努力并获得一个通用、灵活且更具可读性的解决方案,就我而言,我最终将 OR 的结果保存到 ENV 变量中并执行 AND。
# RESULT_ONE = A OR B
RewriteRule ^ - [E=RESULT_ONE:False]
RewriteCond ...A... [OR]
RewriteCond ...B...
RewriteRule ^ - [E=RESULT_ONE:True]
# RESULT_TWO = C OR D
RewriteRule ^ - [E=RESULT_TWO:False]
RewriteCond ...C... [OR]
RewriteCond ...D...
RewriteRule ^ - [E=RESULT_TWO:True]
# if ( RESULT_ONE AND RESULT_TWO ) then ( RewriteRule ...something... )
RewriteCond %ENV:RESULT_ONE =True
RewriteCond %ENV:RESULT_TWO =True
RewriteRule ...something...
要求:
Apache mod_env 已启用【讨论】:
【参考方案2】:这是一个有趣的问题,由于文档中没有非常明确地解释它,我将通过 sourcecode of mod_rewrite 来回答这个问题; 展示了开源的一大优势。
在顶部,您会很快发现defines used to name these flags:
#define CONDFLAG_NONE 1<<0
#define CONDFLAG_NOCASE 1<<1
#define CONDFLAG_NOTMATCH 1<<2
#define CONDFLAG_ORNEXT 1<<3
#define CONDFLAG_NOVARY 1<<4
并搜索CONDFLAG_ORNEXT 确认使用based on the existence of the [OR] flag:
else if ( strcasecmp(key, "ornext") == 0
|| strcasecmp(key, "OR") == 0 )
cfg->flags |= CONDFLAG_ORNEXT;
标志的下一个出现是actual implementation,您将在其中找到遍历 RewriteRule 所具有的所有 RewriteConditions 的循环,它的基本作用是(为了清晰起见,已剥离,添加了 cmets):
# loop through all Conditions that precede this Rule
for (i = 0; i < rewriteconds->nelts; ++i)
rewritecond_entry *c = &conds[i];
# execute the current Condition, see if it matches
rc = apply_rewrite_cond(c, ctx);
# does this Condition have an 'OR' flag?
if (c->flags & CONDFLAG_ORNEXT)
if (!rc)
/* One condition is false, but another can be still true. */
continue;
else
/* skip the rest of the chained OR conditions */
while ( i < rewriteconds->nelts
&& c->flags & CONDFLAG_ORNEXT)
c = &conds[++i];
else if (!rc)
return 0;
你应该能够解释这个;这意味着 OR 具有更高的优先级,并且您的示例确实导致了if ( (A OR B) AND (C OR D) )
。例如,如果您有以下条件:
RewriteCond A [or]
RewriteCond B [or]
RewriteCond C
RewriteCond D
它会被解释为if ( (A OR B OR C) and D )
。
【讨论】:
在我看来,在给出的示例 .htaccess 上执行源代码会产生 ((A OR B) 和 C) 或 D) [即既不是OP希望的,也不是您最初计算的]。你能帮我找出我的解释错误吗? [更明确地说,反过来呢:如果要实现 ((A OR B) AND (C OR D)),.htaccess 文件中的代码到底应该是什么?] +1 表示“展示开源的巨大好处” :) - @ChuckKollars 逻辑不会产生(((A 或 B)和 C)或 D),而是(A 或 B)和(C 或 D)。在每次通过循环时,它都会检查 CONDFLAG_ORNEXT ,它只会在查看 A 和 C 时设置。当它被设置时,如果当前条件通过,它要么跳过下一个条件,要么继续不关心当前条件失败,因为未来条件可能通过并且 OR 组的最后一个不会设置标志,所以如果全部失败,整个事情都会失败。 不知道该怎么做((A 和 B)或(C 和 D)) - 我最终得到了(A 和(B 或 C)和 D) @WillshawMedia 您可以通过将其拆分为两个单独的规则来执行 ((A 和 B) OR (C 和 D)):RewriteCond A RewriteCond B RewriteRule AB RewriteCond C RewriteCond D RewriteRule CD以上是关于如何在 Apache 上对 RewriteCond 使用“AND”、“OR”?的主要内容,如果未能解决你的问题,请参考以下文章