如何在Apache上使用RewriteCond的“AND”,“OR”?

时间:2009-05-28 18:11:24

标签: mod-rewrite apache-config

这是如何在Apache上使用AND,OR用于RewriteCond的?

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)语法?

3 个答案:

答案 0 :(得分:103)

这是一个有趣的问题,因为文档中没有明确解释,我将通过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的循环,它基本上做的是(剥离,为了清晰起见添加注释):

# 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 )

答案 1 :(得分:3)

经过艰苦的努力并寻求通用,灵活和可读性更高的解决方案,我最终将 OR 的结果保存到 ENV 变量中,并进行了<这些变量的strong> 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...

要求

答案 2 :(得分:0)

无法解决这个问题。

具有四个条件的重写规则。
前三个条件A,B,C将为AND,然后与D进行OR

RewriteCond A       true
RewriteCond B       false
RewriteCond C [OR]  true
RewriteCond D       true
RewriteRule ...

但这似乎是 A和B以及(C或D)=假(请勿重写)

如何获得所需的表达式? (A,B和C)或D =真(重写)

最好不使用设置环境变量的其他步骤。

帮助!!!