2009-05-28 11 views
87

E 'questo il modo di usare AND, OR per RewriteCond su Apache?come usare "AND", "OR" per RewriteCond su Apache?

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

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

Quindi sembra che "OR" sia superiore a "AND"? C'è un modo per dirlo facilmente, come nella sintassi (A or B) and (C or D)?

+0

Sì, corretto. [OR] ha una precedenza più alta rispetto al (implicito) "AND". La condizione combinata è infatti ((A o B) e (C o D)). – Doin

+1

È possibile trovare i dettagli in http://www.ckollars.org/apache-rewrite-htaccess.html#precedence utili. –

risposta

86

Questa è una domanda interessante e dal momento che non è spiegata in modo molto esplicito nella documentazione, risponderò a questa domanda passando dallo sourcecode of mod_rewrite; dimostrando un grande vantaggio di open-source.

Nella sezione superiore si prende subito posto il 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 

e alla ricerca di CONDFLAG_ORNEXT conferma che esso è usato based on the existence of the [OR] flag:

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

La prossima ricorrenza della bandiera è la actual implementation dove troverai il ciclo che attraversa tutte le RewriteConditions di cui è dotato RewriteRule e che cosa fa in pratica (spogliato, commenti aggiunti per chiarezza):

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

Dovresti essere in grado di interpretarlo; significa che OR ha una precedenza più alta e il tuo esempio porta infatti a if ((A OR B) AND (C OR D)). Se, per esempio, hanno queste condizioni:

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

sarebbe interpretato come if ((A OR B OR C) and D).

+0

Mi sembra che l'esecuzione del codice sorgente nell'esempio .htaccess dato produce ((A OR B) e C) o D) [vale a dire né ciò che l'OP spera né quello che hai inizialmente calcolato]. Potete aiutarmi a trovare il mio errore di interpretazione? [Anche per essere più esplicito, che dire del contrario: se si vuole implementare ((A O B) E (C O D)), quale dovrebbe essere esattamente un codice nel file .htaccess?] –

+3

+1 per 'dimostrare un grande vantaggio di open-source ':) - @ChuckKollars la logica non produrrebbe (((A o B) e C) o D) ma (A o B) e (C o D). su ogni passaggio attraverso il ciclo controlla CONDFLAG_ORNEXT che verrà impostato solo guardando A e C. Quando viene impostato salta la condizione successiva se la condizione corrente è passata o continua a non preoccuparsi del fatto che la condizione corrente non è riuscita perché le condizioni future potrebbero passare e l'ultimo del gruppo OR non avrà il flag impostato in modo che se tutto fallisce l'intera cosa fallisce. – Logikos

+0

Ottima risposta a una buona domanda. Grazie. – Jpsy