Apache'de RewriteCond için "VE", "VEYA" nasıl kullanılır?


115

AND, OR RewriteCondon Apache için bu nasıl kullanılır ?

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

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

Yani "VEYA", "VE" den daha yüksek önceliğe sahip gibi görünüyor? Söz (A or B) and (C or D)diziminde olduğu gibi bunu kolayca söylemenin bir yolu var mı ?


1
Evet doğru. [VEYA], (örtük) "VE" den daha yüksek önceliğe sahiptir. Birleşik koşul aslında ((A veya B) ve (C veya D)) şeklindedir.
Doin

Yanıtlar:


118

Bu ilginç bir soru ve dokümantasyonda çok açık bir şekilde açıklanmadığından, bunu mod_rewrite'ın kaynak kodunu kullanarak cevaplayacağım ; açık kaynağın büyük bir faydasını gösteriyor .

Üst bölümde, bu bayrakları adlandırmak için kullanılan tanımları hızlı bir şekilde göreceksiniz :

#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

ve CONDFLAG_ORNEXT araması , [VEYA] bayrağının varlığına dayalı olarak kullanıldığını doğrular :

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

Bayrağın bir sonraki oluşumu, bir RewriteRule'un sahip olduğu tüm RewriteConditions'tan geçen döngüyü bulacağınız gerçek uygulamadır ve temelde yaptığı şeydir (açıklık sağlamak için yorumlar eklenmiştir):

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

Bunu yorumlayabilmelisiniz; bu, OR'nin daha yüksek bir önceliğe sahip olduğu anlamına gelir ve sizin örneğiniz gerçekten yol açar if ( (A OR B) AND (C OR D) ). Örneğin, şu Koşullara sahipseniz:

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

olarak yorumlanacaktır if ( (A OR B OR C) and D ).


1
Bana öyle geliyor ki, verilen örnek .htaccess üzerindeki kaynak kodunun çalıştırılması ((A OR B) ve C) veya D) [yani ne OP'nin umduğu ne de başlangıçta hesapladığınız şey] üretir. Yorumlama hatamı bulmama yardım eder misin? [Ayrıca daha açıklamak gerekirse, tersi ne olacak: ((A OR B) VE (C OR D)) uygulamak istiyorsa, .htaccess dosyasındaki bir kod tam olarak ne olmalıdır?]
Chuck Kollars

3
'Açık kaynağın büyük bir faydasını göstermek' için +1 :) - @ChuckKollars mantık (((A veya B) ve C) veya D) değil (A veya B) ve (C veya D) üretecektir. döngü olsa da her geçişte CONDFLAG_ORNEXT'i kontrol eder, bu sadece A ve C'ye bakıldığında ayarlanır. Ayarlandığında, ya mevcut koşul geçerse bir sonraki koşulu atlar ya da mevcut koşulun başarısız olmasını önemsememeye devam eder çünkü gelecekteki koşullar geçer ve OR grubunun sonuncusu bayrağa sahip olmayacaktır, bu yüzden eğer hepsi başarısız olursa, tüm şey başarısız olur.
tempcke

1
((A ve B) YA DA (C ve D)) - (A ve (B veya C) ve D) ile
Pete

@WillshawMedia İki ayrı kurala bölerek ((A ve B) OR (C ve D)) yapabilirsiniz: RewriteCond A RewriteCond B RewriteRule AB RewriteCond C RewriteCond D RewriteRule CD
Isaac

3

Pek çok mücadeleden sonra ve genel, esnek ve daha okunabilir bir çözüme ulaşmak için, benim durumumda OR sonuçlarını ENV değişkenlerine kaydetmeyi ve bu değişkenlerin AND lerini yapmayı bıraktım .

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

Gereksinimler :

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.