【问题标题】:how to use "AND", "OR" for RewriteCond on Apache?如何在 Apache 上对 RewriteCond 使用“AND”、“OR”?
【发布时间】: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) 语法?

【问题讨论】:

标签: mod-rewrite apache-config


【解决方案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...

要求

【讨论】:

    【解决方案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
    猜你喜欢
    • 2013-12-06
    • 2014-05-26
    • 1970-01-01
    • 1970-01-01
    • 2021-01-03
    • 2013-02-19
    • 2012-06-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多