ApacheのRewriteCondに「AND」、「OR」を使用する方法


115

これはRewriteCond、Apacheで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)構文のように、簡単に見分ける方法はあり ますか?


1
はい正解。[OR]は(暗黙の) "AND"よりも優先されます。組み合わせた条件は確かに((AまたはB)および(CまたはD))です。
Doin 2013年

回答:


118

これは興味深い質問であり、ドキュメントではあまり明確に説明されていないため、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を検索すると、[OR]フラグの存在に基づいて使用されていることが確認されます。

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

フラグの次の出現は、RewriteRuleが持つすべてのRewriteConditionsを通過するループが見つかる実際の実装であり、基本的に何をするか(わかりやすくするために削除されたコメント):

# 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 )ます。


1
与えられたサンプル.htaccessでソースコードを実行すると、((A OR B)およびC)またはD)[つまり、OPが期待するものも、最初に計算したものも]が生成されるようです。解釈エラーを見つけるのを手伝ってくれませんか?[また、逆に、逆についてはどうですか:((A OR B)AND(C OR D))を実装したい場合、.htaccessファイルの1つのコードは正確に何ですか?]
Chuck Kollars

3
「オープンソースの大きな利点を実証する」ための+1 :)-@ChuckKollarsロジックは(((AまたはB)およびC)またはD)ではなく(AまたはB)および(CまたはD)を生成します。ループを通過するたびに、AとCを見たときにのみ設定されるCONDFLAG_ORNEXTをチェックします。設定されると、現在の条件が渡された場合に次の条件をスキップするか、将来の条件が原因で現在の条件が失敗したことを気にしない合格し、ORグループの最後はフラグが設定されていないため、すべてが失敗すると、全体が失敗します。
tempcke

1
((AとB)OR(CとD))の方法を頭で理解できません-(Aと(BまたはC)とD)で終わりました
Pete

RewriteCond AのRewriteCond BのRewriteRule ABのRewriteCond CのRewriteCond DのRewriteRule CD:次の2つの別々のルールに分割することによって、((A及びB)又は(C及びD))を行うことができ@WillshawMedia
アイザック

3

多くの苦労の後、一般的で柔軟で読みやすいソリューションを実現するために、私の場合、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...

要件

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.