web-dev-qa-db-fra.com

comment utiliser "AND", "OR" pour RewriteCond sur Apache?

Est-ce la façon d'utiliser AND, OR pour RewriteCond sur Apache?

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

devient if ( (A or B) and (C or D) ) rewrite_it.

Donc, il semble que "OU" est une priorité supérieure à "ET"? Y a-t-il un moyen de le savoir facilement, comme dans la syntaxe (A or B) and (C or D)?

105

C'est une question intéressante et comme cela n'est pas expliqué de manière très explicite dans la documentation, je vais y répondre en passant par le code source de mod_rewrite ; démontrant un gros avantage de open-source.

Dans la section supérieure, vous remarquerez rapidement le définit utilisé pour nommer ces drapeaux :

#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

et la recherche de CONDFLAG_ORNEXT confirme son utilisation en fonction de l’existence de l’indicateur [OR] :

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

La prochaine occurrence du drapeau est le implémentation réelle où vous trouverez la boucle qui parcourt toutes les conditions RewriteConditions qu’un RewriteRule possède, et dont il fait l’objet (effets supprimés, commentaires ajoutés pour plus de clarté):

# 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;
    }
}

Vous devriez pouvoir interpréter cela. cela signifie que OR a une priorité plus élevée et votre exemple conduit en effet à if ( (A OR B) AND (C OR D) )]. Si vous souhaitez, par exemple, avoir ces conditions:

RewriteCond A [or]
RewriteCond B [or]
RewriteCond C
RewriteCond D

il serait interprété comme if ( (A OR B OR C) and D ).

106
Sjon