Как использовать «И», «ИЛИ» для RewriteCond на Apache? - PullRequest
103 голосов
/ 28 мая 2009

Это как использовать И, ИЛИ для RewriteCond на Apache?

rewritecond A [or]
rewritecond B
rewritecond C [or]
rewritecond D
RewriteRule ... something

становится if ( (A or B) and (C or D) ) rewrite_it.

Так что кажется, что "ИЛИ" имеет более высокий приоритет, чем "И"? Есть ли способ легко сказать, как в синтаксисе (A or B) and (C or D)?

1 Ответ

104 голосов
/ 22 июля 2015

Это интересный вопрос, и поскольку он не очень подробно объясняется в документации, я отвечу на него, пройдя исходный код 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

и поиск CONDFLAG_ORNEXT подтверждает, что он используется в зависимости от наличия флага [ИЛИ] :

else if (   strcasecmp(key, "ornext") == 0
         || strcasecmp(key, "OR") == 0    ) {
    cfg->flags |= CONDFLAG_ORNEXT;
}

Следующее вхождение флага - это фактическая реализация , где вы найдете цикл, который проходит через все RewriteConditions, которые есть у RewriteRule, и то, что он в основном делает (лишенные комментарии для ясности добавлены) :

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

...