Send Docs Feedback

Note: Most user interface tasks can be performed in Edge Classic or the New Edge experience. For an overview, getting started topics, and release notes specific to the New Edge experience, see the docs.

条件文でのパターン照合

This topic explains how to use these pattern matching operators in conditional statements in Apigee Edge:

  • Matches 演算子
  • JavaRegex 演算子
  • MatchesPath 演算子

Conditional statements are used in conditional flows, routes, and steps. You can read more about conditional statements in the Conditions reference.

実験

You can experiment with the conditions described in this topic, and make up and test your own conditions, using the condition-pattern-matching proxy in our api-platform-samples repository in GitHub. See the README for details. 

Matches 演算子による単純な照合

まずは 「Matches」または 「~」条件演算子から見てみましょう。これら 2 つの演算子は同じものですが、英単語の形である「Matches」の方が読みやすいと考えられます。

概要: 「Matches」演算子では、2 種類のやり方があります。文字列をそのまま照合するか、「*」によるワイルドカード照合を行うかです。ご存知かもしれませんが、ワイルドカード照合は0字以上の文字と一致します。それでは、その動作を見てみましょう。

The following XML shows a Step condition. It executes the SomePolicy policy when the condition evaluates to true. In this example, we test the variable proxy.pathsuffix, a built-in variable in Edge that stores the path suffix of the request. Note, however, you can test the value of any flow variable that contains a string. So, in this case, if the base path of the incoming request is /animals, and the request is /animals/cat, then the path suffix is the literal string "/cat".

    <PreFlow name="PreFlow">
        <Request>
            <Step>
                <Condition>(proxy.pathsuffix Matches "/cat")</Condition>
                <Name>SomePolicy</Name>
            </Step>
        </Request>
        <Response/>
    </PreFlow>

質問: SomePolicy の実行を引き起こすプロキシのパスサフィックスは何ですか? 可能性は 1 つしかありません。

API 呼び出し:

GET http://artomatic-test.apigee.net/matchtest/cat

ポリシーは実行されるでしょうか? はい。プロキシのパスサフィックスが「/cat」と完全に一致しているためです。サフィックスが「/bat」、「/dog」、「/」など、他のどのような場合も実行されません。

では、ワイルドカード文字「*」を使用する条件文について考えてみましょう。

<Condition>(proxy.pathsuffix Matches "/*at")</Condition>

API 呼び出し:

GET http://artomatic-test.apigee.net/matchtest/cat

ポリシーは実行されるでしょうか? はい。ワイルドカードはあらゆる文字と一致し、「/cat」が一致内容です。

API 呼び出し:

GET http://artomatic-test.apigee.net/matchtest/bat

ポリシーは実行されるでしょうか? はい。ワイルドカードはあらゆる文字と一致し、「/bat」が一致内容です。

API 呼び出し:

GET http://artomatic-test.apigee.net/matchtest/owl

ポリシーは実行されるでしょうか? 実行されません。ワイルドカードは「o」と一致しますが、文字列「wl」とは一致しません。

では、ワイルドカードをサフィックスの末尾に移動してみましょう。

<Condition>(proxy.pathsuffix Matches "/cat*")</Condition>

API 呼び出し:

GET http://artomatic-test.apigee.net/matchtest/cat

Does the policy execute? Yes, because the wildcard matches zero or more of any characters.

API 呼び出し:

GET http://artomatic-test.apigee.net/matchtest/bat

ポリシーは実行されるでしょうか? いいえ。「/bat」は一致する内容ではありません。

API 呼び出し:

GET http://artomatic-test.apigee.net/matchtest/cat123

Does the policy execute? Yes, the wildcard matches zero or more of any characters, therefore "123" produces a match.

API 呼び出し:

GET http://artomatic-test.apigee.net/matchtest/cat/bird/mouse

Does the policy execute? Yes, because the wildcard matches zero or more of any characters, so "/bird/mouse" produces a match. Note how an expression like this can get you into trouble because it matches everything after the literal characters!

Matches 演算子は大文字小文字が区別されますか?

はい。次のような条件があるものとしてください。

<Condition>(proxy.pathsuffix Matches "/*At")</Condition>

API 呼び出し:

GET http://artomatic-test.apigee.net/matchtest/cat

ポリシーは実行されるでしょうか? いいえ。ワイルドカードは (英文字の大小に関係なく) あらゆる文字と一致しますが、小文字の「a」が大文字の「A」と一致していません。 

API 呼び出し:

GET http://artomatic-test.apigee.net/matchtest/bAt

ポリシーは実行されるでしょうか? はい、英文字の大小が一致しています。 

Matches 演算子で、文字をエスケープするにはどうすればよいですか?

予約済みの文字をエスケープするには、「%」を使用します。例:

<Condition>(proxy.pathsuffix Matches "/c%*at")</Condition>

API 呼び出し:

GET http://artomatic-test.apigee.net/matchtest/cat

ポリシーは実行されるでしょうか? いいえ。Matches 演算子はリテラル文字列「c*at」を探します。 

API 呼び出し:

GET http://artomatic-test.apigee.net/matchtest/c*at

ポリシーは実行されるでしょうか? はい。このパスはちょっと一般的には見られませんが、一致します。

 

JavaRegex によるきめ細かな制御

ご承知のように、「Matches」演算子は単純な状況には最適です。ただし、別の演算子である「JavaRegex」または「~~」演算子を使用することもできます。これらの 2 つは同じ演算子ですが、JavaRegex の方が判読しやすいと考えられます。JavaRegex と呼ぶのは、正規表現パターン照合が可能であり、Edge では、Java 言語の java.util.regex パッケージ内のクラスと同じルールに従うためです。JavaRegex 演算子の動作は、Matches 演算子の動作とはかなり異なるため、これらの 2 つを混同しないことが重要です。

If you're used to doing Regex in Perl scripts, it's important to note that the JavaRegex operator in Edge tests the entire subject string. For example, if the subject is "abc" and the regex is "[a-z]" , there is no match because "[a-z]" matches exactly ONE alpha character. The expression "[a-z]+" would work, as would "[a-z]{3}". This matching differs from the usual application of regular expressions in tools like Perl or grep or Apache's mod_rewrite. JavaRegex uses java.util.regex.Pattern.matches(str), which is defined to return positive if the entire string (str) matches the pattern. The regex in Perl or mod_rewrite are applied to "any" part of the string. They return true if the pattern matches anywhere. See the example Matching arbitrary strings with JavaRegex.

This section is not intended to be a detailed introduction to regular expressions. The main intent is to illustrate a few simple examples, and highlight the difference between the Matches and JavaRegex operators. If you'd like to know more about regular expressions, many resources exist for you to explore. 

まとめ: 「JavaRegex」演算子では、条件文で正規表現の構文を使用できます。

The following code shows a Step condition. It executes the SomePolicy policy if the condition evalutes to true. In this example, we test the variable proxy.pathsuffix, a built-in variable in Edge that stores the path suffix of the request. Note, however, you can test the value of any flow variable that contains a string. So, in this case, if the base path of the incoming request is /animals, and the request is /animals/cat, then the path suffix is the literal string "/cat".

    <PreFlow name="PreFlow">
        <Request>
            <Step>
                <Condition>(proxy.pathsuffix JavaRegex "/cat")</Condition>
                <Name>SomePolicy</Name>
            </Step>
        </Request>
        <Response/>
    </PreFlow>

Question: What proxy path suffix will cause SomePolicy to execute? Just like with the Matches operator, there's only one possibility in this case.

API 呼び出し:

GET http://artomatic-test.apigee.net/matchtest/cat

ポリシーは実行されるでしょうか? はい。プロキシのパスサフィックスが「/cat」と完全に一致するためです。サフィックスが「/bat」、「/dog」など、他のどのような場合も実行されません。

Now, let's create a regular expression using "*" quantifier. This quantifier matches zero or more of the preceeding character.

<Condition>(proxy.pathsuffix JavaRegex "/c*t")</Condition>

API 呼び出し:

GET http://artomatic-test.apigee.net/matchtest/cat

Does the policy execute? No! The "*" quantifier matches zero or more of the preceeding character, which is a "c".

API 呼び出し:

GET http://artomatic-test.apigee.net/matchtest/ccccct

ポリシーは実行されるでしょうか? はい。ワイルドカードは、先行する文字の 0 字以上と一致するためです。


Next, we use the "?" quantifier, which matches the preceeding character once, or not at all.

<Condition>(proxy.pathsuffix JavaRegex "/ca?t")</Condition>

API 呼び出し:

GET http://artomatic-test.apigee.net/matchtest/cat

Does the policy execute? Yes. The "?" quantifier matches zero or one occurance of the preceeding character, which is an "a".

API 呼び出し:

GET http://artomatic-test.apigee.net/matchtest/ct

Does the policy execute? Yes. The "?" quantifier matches one or none of the preceeding character. In this case, there is no "a" character, so the condition evaluates to true.

API 呼び出し:

GET http://artomatic-test.apigee.net/matchtest/caat

ポリシーは実行されるでしょうか? いいえ。「?」数量子は、先行する文字の 1 つ (ここでは「a」) と一致します。

 

Next, we use the "[abc]" or "grouping" style of regex expression. It matches the characters "a" or "b" or "c".

<Condition>(proxy.pathsuffix JavaRegex "/[cbr]at)</Condition>

API 呼び出し:

GET http://artomatic-test.apigee.net/matchtest/cat

ポリシーは実行されるでしょうか? はい。ここでは正規表現を使用しており、「[cbr]」式は、「c」、「b」、または「r」に一致します。以下の呼び出しも一致します。

GET http://artomatic-test.apigee.net/matchtest/bat

GET http://artomatic-test.apigee.net/matchtest/rat

しかし、次は一致しません。

GET http://artomatic-test.apigee.net/matchtest/mat

 

JavaRegex は英文字の大小を区別しますか?

はい。次のような条件があるものとしてください。

<Condition>(proxy.pathsuffix Matches "/ca?t")</Condition>

API 呼び出し:

GET http://artomatic-test.apigee.net/matchtest/cat

ポリシーは実行されるでしょうか? はい。この正規表現は、先行する文字 (ここでは「a」) の 0 字または 1 字と一致します。  

API 呼び出し:

GET http://artomatic-test.apigee.net/matchtest/cAt

ポリシーは実行されるでしょうか? いいえ。大文字「A」が小文字「a」と一致しないためです。

MatchesPath 演算子によるパスフラグメントの照合

The MatchesPath operator can also be specified like this "~/". It looks a little bit like the Matches (~) and the JavaRegex (~~) operators. But MatchesPath is entirely different.

この演算子は、パスを一連のパーツの組み合わせとして確認します。そのため、パスが /animals/cats/wild の場合は、パスをパーツ「/animals」、「/cats」、および「/wild」から構成されていると考えることができます。

MatchesPath 演算子では、2 種類のワイルドカード表記 (1 つのアスタリスク (*) と 2 つのアスタリスク (**)) を使用できます。 アスタリスクが 1 つの場合、1 つのパス要素と一致します。アスタリスクが 2 つの場合、1 つまたは複数のパス要素と一致します。

Let's look at an example. In this example, we test the variable proxy.pathsuffix, a built-in variable in Edge that stores the path suffix of the request. Note, however, you can test the value of any flow variable that contains a string.

    <PreFlow name="PreFlow">
        <Request>
            <Step>
                <Condition>(proxy.pathsuffix MatchesPath "/animals/*)</Condition>
                <Name>SomePolicy</Name>
            </Step>
        </Request>
        <Response/>
    </PreFlow>

質問: SomePolicy の実行を引き起こすプロキシのパスサフィックスは何ですか?

API 呼び出し:

GET http://artomatic-test.apigee.net/matchtest/animals

ポリシーは実行されるでしょうか? いいえ。条件から、/animals の後ろに、「/*」で指定される別のパス要素が要求されているためです。

API 呼び出し:

GET http://artomatic-test.apigee.net/matchtest/animals/

ポリシーは実行されるでしょうか? はい。このパスには別のパス要素 (/animals/ の後ろのパーツ) がありますが、空白にすぎません。

API 呼び出し:

GET http://artomatic-test.apigee.net/matchtest/animals/cats

ポリシーは実行されるでしょうか? はい。このパスには、「/animals」の後ろに来る要素 (「/cats」) が明確に存在しています。

API 呼び出し:

GET http://artomatic-test.apigee.net/matchtest/animals/cats/wild

ポリシーは実行されるでしょうか? いいえ。アスタリスクが 1 つの場合、1 つのパス要素にのみ一致しますが、この API では、「/animals」の後ろに複数の要素が存在します。

次に、2 つのアスタリスクを使ってみましょう。

    <PreFlow name="PreFlow">
        <Request>
            <Step>
                <Condition>(proxy.pathsuffix MatchesPath "/animals/**)</Condition>
                <Name>SomePolicy</Name>
            </Step>
        </Request>
        <Response/>
    </PreFlow>

質問: SomePolicy の実行を引き起こすプロキシのパスサフィックスは何ですか?

API 呼び出し:

GET http://artomatic-test.apigee.net/matchtest/animals

ポリシーは実行されるでしょうか? いいえ。条件から、「/**」によって指定される後続のパス要素が少なくとも 1 つ要求されているためです。

API 呼び出し:

GET http://artomatic-test.apigee.net/matchtest/animals/

ポリシーは実行されるでしょうか? はい。このパスには別のパス要素 (/animals/ の後ろのパーツ) がありますが、空白にすぎません。

API 呼び出し:

GET http://artomatic-test.apigee.net/matchtest/animals/cats

ポリシーは実行されるでしょうか? はい。このパスには、「/animals」の後ろに要素が少なくとも 1 つあります。

API 呼び出し:

GET http://artomatic-test.apigee.net/matchtest/animals/cats/wild

ポリシーは実行されるでしょうか? はい。このパスには、「/animals」の後ろに要素が複数あります。

アスタリスクの混合

1 つのアスタリスク (*) と 2 つのアスタリスク (**) を組み合わせて、パス照合をさらにきめ細かくすることができます。

    <PreFlow name="PreFlow">
        <Request>
            <Step>
                <Condition>(proxy.pathsuffix MatchesPath "/animals/*/wild/**)</Condition>
                <Name>SomePolicy</Name>
            </Step>
        </Request>
        <Response/>
    </PreFlow>

API 呼び出し:

All of these API calls will produce a match:

GET http://artomatic-test.apigee.net/matchtest/animals/cats/wild/

and

GET http://artomatic-test.apigee.net/matchtest/animals/dogs/wild/austrailian

and

GET http://artomatic-test.apigee.net/matchtest/animals/birds/wild/american/finches

A practical example: Ignore "/" at the end of a path

Edge developers commonly want to handle both of these path suffixes: "/cat" and "/cat/". This is because some users or clients might call your API with the extra slash on the end of the path, and you need to be able to handle that in your conditional statements. This exact use case has been discussed on the Apigee Community.

If you prefer, you can achieve this without using Regex like this:

    <PreFlow name="PreFlow">
        <Request>
            <Step>
                <Condition>((proxy.pathsuffix = "/cat") OR (proxy.pathsuffix = "/cat/")</Condition>
                <Name>SomePolicy</Name>
            </Step>
        </Request>
        <Response/>
    </PreFlow>

This is a good option. It is clear and readable.

You can do the same thing with Regex, however, like this. The parentheses are used to group the regex part of the statement, but they are not required.

<Condition>(proxy.pathsuffix JavaRegex "/cat(/?)"</Condition>

API Calls:

GET http://artomatic-test.apigee.net/matchtest/cat
or 

GET http://artomatic-test.apigee.net/matchtest/cat/

Does the policy execute? Yes. Note that in a regular expression, the "?" character means: match zero or one of the preceeding character. Therefore, both "/cat" and "/cat/" are matches.

API 呼び出し:

GET http://artomatic-test.apigee.net/matchtest/cat/spotted

Does the policy execute? No. The regular expression matches zero or only one occurance of the preceeding character, and nothing else is allowed.

Matching arbitrary strings with JavaRegex

In all of the examples in this topic, we show how to match one of the built-in flow variables: proxy.pathsuffix. It's good to know that you can do pattern matching on any arbitrary string or flow variable, whether or not it's a built-in flow variable like proxy.pathsuffix. 

If for example you have a condition that tests an arbitrary string, perhaps a string returned in a backend payload, or a string returned from an authentication server lookup, you can use matching operators to test it. If you use JavaRegex, the regular expression will be compared against the entire subject string. If the subject is "abc" and the regular expression is "[a-z]", there is no match, because "[a-z]" matches exactly one alpha character. The expression "[a-z]+" works, as does "[a-z]*", and "[a-z]{3}.

Let's look at a concrete example. Suppose the authentication server returns a list of roles as a comma-delimted string: "editor, author, guest".

To test the presence of the editor role, this construction will not work, because "editor" is only part of the entire string.

<Condition>returned_roles ~~ "editor"</Condition>

However, this construction will work:

<Condition>returned_roles ~~ ".*\beditor\b.*")</Condition>

It works because it takes into account word breaks and any other parts of the string with the .* prefix and suffix. 

In this example, you can also test for "editor" with the Matches operator:

<Condition>returned_roles ~~ "*editor*")</Condition>

However, in cases where you need more precision, JavaRegex is often a better choice. 

 

 

Help or comments?