Was this helpful?

Conditions enable API proxies to behave dynamically at runtime. Conditions define operations on variables, which are evaluated by the Apigee Edge processing pipeline. Conditional statements are boolean and always evaluate to true or false.

Apigee specifies a set of commonly used variables. For a complete list, see Variables reference. Custom variables can also be used in conditional statements. For instructions, see on setting custom variables, see Extract message content using ExtractVariables

The basic structure of a conditional statement is:

<Condition>{variable.name}{operator}{"value"}</Condition>

For example:

<Condition>request.verb = "GET"</Condition>

Conditions can be chained. For example, the following condition evaluates to true only if the URI of the request matches /statuses/user_timeline.json and the HTTP verb of the request is GET.

<Condition>(proxy.pathsuffix MatchesPath "/statuses") and (request.verb = "GET")</Condition>

Or:

(proxy.pathsuffix MatchesPath "/statuses") and (request.verb != "GET")

Conditional behavior is supported by three components of an API proxy:

Policy enforcement

Using conditional statements, you can control the enforcement of policies. A common use case is conditional transformation of response messages, based on HTTP header or message content.

For example, to conditionally transfrom XML to JSON based on the Accept header:

<Step>
  <Condition>request.header.accept = "application/json"</Condition>
  <Name>XMLToJSON</Name>
</Step>

Flow execution

Using conditional statements, you can control the execution of named flows in ProxyEndpoints and TargetEndpoints. Note that only 'named' flows can be executed conditionally. Preflows and postflows (both request and response) on ProxyEndpoints and TargetEndpoints execute for every transaction, and thus provide unconditional 'failsafe' capabilities.

For example, to execute a conditional request flow based on the HTTP verb of the request message, and conditional response flow based on a (potential) HTTP error code:

<Flow name="GetRequests">
  <Condition>response.verb = "GET"</Condition>
  <Request>
    <Step>
      <Condition>request.path MatchesPath "/statuses/**"</Condition>
      <Name>StatusesRequestPolicy</Name>
    </Step>
  </Request>
  <Response>
    <Step>
      <Condition>(response.status.code = 503) or (response.status.code = 400)</Condition>
      <Name>MaintenancePolicy</Name>
    </Step>
  </Response>
</Flow>

Routes

Using conditional statements, you can control the target endpoint invoked by proxy endpoint configuration. A route rule forwards a request to a particular target endpoint. When more than one target endpoint is available, the route rule is evaluated for its condition and, if true, the request is forwarded to the named target endpoint.

For example, to conditionally route messages to designated target endpoints based on Content-Type:

<RouteRule name="target"> 
  <Condition>target-variable = "targets"</Condition> 
  <TargetEndpoint>targets</TargetEndpoint> 
</RouteRule> 
  <RouteRule name="default"> 
  <TargetEndpoint>default</TargetEndpoint> 
</RouteRule>

See Create dynamic API flows using conditions for more information.

Path Expressions

Path expressions are used for matching URI paths., using "*" to represent a single path element and "**" to represent multiple URI levels.

For example:

Pattern URIPath values extracted
/*/a/{v1} /x/y/z no value extracted
/*/a/{v1} /x/a/b v1=b
/*/a/{v1} /x/a/b/c/d v1=b
/*/a/{v1} /x/a/b;jsessionid=123456 v1=b
/*/a/{v1} /x/y/z no value extracted
/*/a/{v1} /x/a/b v1=b
/*/a/{v1} /x/a/b/c/d v1=b
/*/a/{v1} /x/a/b;jsessionid=123456 v1=b
/a/**/feed/{v1}/{v2} /a/b/feed/rss/1234 v1=rss v2=1234
/a/**/feed/{v1}/{v2} /a/b/c/d/feed/rss/5678 v1=rss v2=5678
/a/**/feed/{v1}/{v2} /a/b/c/feed/rss/5678/d/feed/atom/9876 v1=rss v2=9876

% is treated as escape character. The pattern hello %{user%}{symbol} matches hello {user}! but not hello world!.

Conditions can be categorized as follows:

  • Operators: Wildcard patterns used in conditions.
  • Relational operands: Evaluates whether a quantity is equal to, greater than, or less than another.
  • Operands: The value of the conditions is used to determine the overall values.
  • Literals: Literal values in a condition.

Operators

When using operators, observe the following restrictions:

  • Operators cannot be used as variable names.
  • A space character is required before and after an operator.
  • To include an operator in a variable, a variable name must be enclosed in single quotes. For example, 'request.header.help!me'.
  • Arithmetic operators are supported (+, *, -, /, %).
  • Java precedence is used for operators.
  • Apigee Edge relies on regular expressions as implemented in java.util.regex.
Symbol In words (case insensitive) Description
! Not, not Unary operator (takes a single input)
= Equals, Is Equals to
!= NotEquals, IsNot Not equals
:= EqualsCaseInsensitive Equals but is case insensitive
> GreaterThan Greater than
>= GreaterThanOrEquals Greater than or equal to
< LesserThan Lesser than
<= LesserThanOrEquals Lesser than or equal to
&& And, and And
|| Or Or
(   Groups an expression
)   Closes an expression group
~~ JavaRegex Matches a javax.util.regex compliant regular expression
~/ MatchesPath, LikePath Matches a path expression
=| StartsWith Starts with

Relational operators and null operands

The following table shows the behavior when operands evaluate to null.

Operator LHS null RHS null LHS and RHS null
=, ==, := false false true
=| false false false
!= true true false
> true false false
>= false true true
< true false false
<= true false true
~ false N/A false
!~ true false false
~/ false N/A false

Operands

Data types are defined for variables, so values can be adapted as needed for comparison. For example, the response status code = "404" is not a valid comparison because the response status code is an integer and not a string.

The system is configured to adapt operands to a common data type before comparing them. For example, if the response status code is 404, the expression response.status.code = "400" and the response.status.code = 400 are equivalent.

For numeric operands, the data type is interpreted as integer unless the value is terminated as follows:

  • "f" or "F" (float, for example, 3.142f, 91.1F)
  • "d" or "D" (double, for example, 3.142d, 100.123D)
  • "l" or "L" (long, for example, 12321421312L)

In these cases, the system performs the adaptations shown in the following table.

Note: The dash character ( - ) in this table implies that the comparison is not performed, so the comparison is false.

RHS LHS Boolean Integer Long Float Double String Comparable Object
Boolean Boolean Integer Long Float Double String   -
Integer Integer Integer Long Float Double String Comparable -
Long Long Long Long Float Double String Comparable -
Float Float Float Float Float Double String Comparable -
Double Double Double Double Double Double String Comparable -
String String String String String String String Comparable -
Comparable Comparable Comparable Comparable Comparable Comparable Comparable Comparable -
Object - - - - - - - -

Literals

Null, true, and false are the literals available in conditions. For example:

  • request.header.host is null
  • flow.cachehit is true

Samples

<RouteRule name="default">
     <Condition>request.header.content-type = "text/xml"</Condition>
     <TargetEndpoint>XmlTargetEndpoint</TargetEndpoint>
</RouteRule>
<Step>
    <Condition>response.status.code is 503</Condition>
    <Name>MaintenancePolicy</Name>
</Step>
<Flow name="GetRequests">
    <Condition>response.verb="GET"</Condition>
    <Request>
        <Step>
            <Condition>request.path ~ "/statuses/**"</Condition>
            <Name>StatusesRequestPolicy</Name>
        </Step>
    </Request>
    <Response>
        <Step>
            <Condition>(response.status.code = 503) or (response.status.code = 400)</Condition>
            <Name>MaintenancePolicy</Name>
        </Step>
    </Response>
</Flow>

コメント

How does termination work? If I want to match "foo" in:
/foo/bar/baz

Can I specify:
/{foo}/

… or do I have to do something like:
/{foo}/**

コメントを追加

Provide your email address if you wish to be contacted offline about your comment.
We will not display your email address as part of your comment.

We'd love your feedback and perspective! Please be as specific as possible.
Type the characters you see in this picture. (verify using audio)

Type the characters you see in the picture above; if you can't read them, submit the form and a new image will be generated. Not case sensitive.