nop*_*ole 110 mod-rewrite apache-config
这是如何RewriteCond在Apache上使用AND,OR ?
rewritecond A [or]
rewritecond B
rewritecond C [or]
rewritecond D
RewriteRule ... something
Run Code Online (Sandbox Code Playgroud)
成为if ( (A or B) and (C or D) ) rewrite_it.
所以看起来"OR"的优先级高于"AND"?有没有办法轻松讲述,比如 (A or B) and (C or D)语法?
Sjo*_*jon 110
这是一个有趣的问题,因为在文档中没有非常明确地解释,我将通过浏览mod_rewrite的源代码来回答这个问题.展示了开源的巨大好处.
#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
Run Code Online (Sandbox Code Playgroud)
并且搜索CONDFLAG_ORNEXT确认它是根据[OR]标志的存在使用的:
else if ( strcasecmp(key, "ornext") == 0
|| strcasecmp(key, "OR") == 0 ) {
cfg->flags |= CONDFLAG_ORNEXT;
}
Run Code Online (Sandbox Code Playgroud)
下一次出现的标志是实际的实现,你可以在其中找到经过RewriteRule所有RewriteConditions的循环,它基本上做的是(剥离,为了清晰起见添加了注释):
# 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;
}
}
Run Code Online (Sandbox Code Playgroud)
你应该能够解释这个; 这意味着OR具有更高的优先级,并且您的示例确实会导致if ( (A OR B) AND (C OR D) ).例如,如果您有这些条件:
RewriteCond A [or]
RewriteCond B [or]
RewriteCond C
RewriteCond D
Run Code Online (Sandbox Code Playgroud)
它将被解释为if ( (A OR B OR C) and D ).
经过多次努力并获得通用、灵活且更具可读性的解决方案,在我的情况下,我最终将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...
Run Code Online (Sandbox Code Playgroud)
要求: