Controlling API proxies with flows

This page applies to Apigee and Apigee hybrid.

View Apigee Edge documentation.

Flows are the basic building blocks of API proxies. Flows enable you to program the behavior of an API by letting you configure the sequence in which policies and code are executed by an API proxy.

Flows are sequential stages along the API request processing path. When you add proxy logic, such as to verify an API key, you add the logic as a step in the sequence specified by a flow. When you define a condition to specify whether and when logic executes, you add the condition to a flow.

The following flow configuration example defines a flow in which the VerifyAPIKey policy executes if the incoming request path ends with / and the request's HTTP verb is GET.

<Flow name="Get Food Carts">
    <Description>Get Food Carts</Description>
    <Request>
        <Step>
            <Name>Verify-API-Key</Name>
        </Step>
    </Request>
    <Condition>(proxy.pathsuffix MatchesPath "/") and (request.verb = "GET")</Condition>
</Flow>

The Verify-API-Key value in the flow's <Name> element serves to include a policy configured elsewhere in the proxy with XML such as the following:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<VerifyAPIKey async="false" continueOnError="false" enabled="true" name="Verify-API-Key">
    <DisplayName>Verify API Key</DisplayName>
    <Properties/>
    <APIKey ref="request.header.x-api-key"/>
</VerifyAPIKey>

Designing flow execution sequence

You structure flows so that you can have logic execute in the right sequence along the processing path.

When deciding where to add logic, you'll first choose whether to add it to a proxy endpoint or target endpoint. An API proxy divides its code between code that interacts with the proxy's client (proxy endpoint) and optional code that interacts with the proxy's backend target, if any (target endpoint).

Both endpoints contain flows, as described here:

Endpoint type Description Flows supported
ProxyEndpoint Contains the API proxy flows closest to the client. Provides places for logic to act first on the request from the client, then last on the response to the client. PreFlow, conditional flows, PostFlow, PostClientFlow
TargetEndpoint Contains the API proxy flows closest to the backend resource. Provides places for logic to prepare a request for, then handle the response from, a backend resource. PreFlow, conditional flows, PostFlow

You configure flow with XML that specifies what should happen and in what order. The following illustration shows how flows are ordered sequentially within a proxy endpoint and target endpoint:

Request from HTTP client passing through Proxy Endpoint to the TargetEndpoint on the
  backend to reach the HTTP service. Each request and response panel shows the preflow, conditional
  flows, and post flow. In addition, examples of the proxy endpoint and target endpoint are
  provided.

The proxy endpoint and target endpoint each contain flows that you can arrange in the following sequence:

Position Flow type Description
1 PreFlow

Useful when you need to make sure that certain code executes before anything else happens.

If the PreFlow is in a target endpoint, it executes after the proxy endpoint's PostFlow.

2 Conditional Flow

The place for conditional logic. Executes after the PreFlow and before the PostFlow.

Only one conditional flow is executed per segment--the first flow whose condition evaluates to true. That means you can have one conditional flow executed as part of each of the:

  • ProxyEndpoint's request pipeline
  • TargetEndpoint's request pipeline
  • ProxyEndpoint's response pipeline
  • TargetEndpoint's response pipeline
3 PostFlow

A good place to need to log data, send a notification that something happened while processing the request, and so on. Executes after conditional flows and PreFlow.

If the PostFlow is in a proxy endpoint, and there's a target endpoint, the proxy endpoint PostFlow executes before the target endpoint PreFlow.

4 PostClientFlow (proxy flow only) A flow for logging messages after a response is returned to the client.

Having code execute first with a PreFlow

A PreFlow is useful when you need to make sure that certain code executes before anything else happens.

In a proxy endpoint, a PreFlow is a great place for code that authenticates a client and limits traffic from clients. In a target endpoint, where it begins preparing to send a request to a backend target, a PreFlow is good for first steps in preparing to send the request.

For example, you usually don't want to service a client that has exceeded its quota. To support these requirements, you put security and quota policies in the PreFlow segment. That way, you don't need to worry about a condition failing to evaluate in a later conditional flow. The policies in this flow will always execute before any other processing takes place.

In the following example, SpikeArrest and Quota policies execute before processing passes to conditional flows.

<PreFlow name="MyPreFlow">
    <Request>
        <Step>
            <Name>Spike-Arrest</Name>
        </Step>
        <Step>
            <Name>Quota</Name>
        </Step>
    </Request>
    <Response/>
</PreFlow>

Having code execute conditionally with a conditional flow

Between a PreFlow and a PostFlow, you can have flows that execute conditionally. This gives you an opportunity to configure multiple sequences of logic, but have only one execute based on your proxy's state. A conditional flow is optional if you can execute all logic in PreFlow or PostFlow and no conditions are required (in other words, only one path through the endpoint is supported).

Each flow specifies a condition that tests for different state values. This effectively branches execution based on conditions. For example, you might want to convert XML to JSON only when the requesting app is running on a mobile device.

Here, quota constraints are enforced only if the request is a GET request with a URI pattern of /issue/** (/issue/ with anything in the URI after the last forward slash).

<Flow name="MyFlow">
    <Description/>
    <Request>
        <Step>
            <Name>Quota</Name>
        </Step>
    </Request>
    <Response/>
    <Condition>(proxy.pathsuffix MatchesPath "/issue/**") and (request.verb = "GET")</Condition>
</Flow>

You use flow variables to specify conditions. For more about using variables in conditions, see Conditions with flow variables.

For examples of using pattern matching in conditions, see Pattern matching.

Having code execute after core logic with a PostFlow

A PostFlow is a great place to perform actions after your endpoint's core logic, and before endpoint processing finishes. A PostFlow executes after conditional flows and PreFlow.

A PostFlow is a good place to log some data, send a notification that something happened, transform the response message format, and so on.

In the following example, an AssignMessage policy called SetResponseHeaders sets headers of the response message before Apigee sends the response back to the client.

<PostFlow>
    <Response>
        <Step>
            <Name>SetResponseHeaders</Name>
        </Step>
    </Response>
 </PostFlow>

Having code execute after the client receives your proxy's response with a PostClientFlow

A PostClientFlow can include the following policies only. No other policies can be used in a PostClientFlow:

* The FlowCallout policy can only call shared flows which themselves meet the criteria for being in the PostClientFlow (ie, only contain compatible policies).

If you include one, a PostClientFlow would be the last flow to execute, executing after a response is sent to the client.

A PostClientFlow is good for final logging. Also, you can log the start and end timestamps for the response message.

Here's an example of a PostClientFlow with a MessageLogging policy attached.


  <ProxyEndpoint name="endpoint1">
    ...
    <PostFlow name="PostFlow">
        <Request/>
        <Response/>
    </PostFlow>
    <PostClientFlow>
        <Response>
            <Step>
                <Name>Message-Logging-1</Name>
            </Step>
        </Response>
    </PostClientFlow>
    ...
  </ProxyEndpoint>

For more information, see API proxy configuration reference.

Adding logic to flows

When you add logic to your proxy, you do it by adding policies to your proxy's flows. Just as flows execute in a sequence (PreFlow then Flow then PostFlow, as described in this topic), the contents of a flow execute in a sequence.

The following example flow configuration references three policies (configured elsewhere in their own XML files). The policy referenced by Verify-API-Key executes before the policy referenced by Assign-Message; both are followed by the policy represented by Quota.

<Flow name="Get Food Cart Menus">
  <Description>Get Food Cart Menus</Description>
  <Request>
    <Step>
      <Name>Verify-API-Key</Name>
    </Step>
    <Step>
      <Name>Assign-Message</Name>
    </Step>
    <Step>
      <Name>Quota</Name>
    </Step>
  </Request>
  <Condition>(proxy.pathsuffix MatchesPath "/") and (request.verb = "GET")</Condition>
</Flow>

Debugging flows

The Debug tool provides a graphical way to see how the logic in your API proxy executes following a request. The tool illustrates processing between request and response. It doesn't specifically illustrate the separation between PreFlow, conditional flows, and PostFlow.

For more about debugging proxies, see Using the Debug tool.

Handling errors in flows

You can raise faults from various places in an API proxy, including from flows.

The following example is the response stanza from a PreFlow in a target endpoint—in other words, it's the code that executes immediately upon receiving the response from a backend target. In the example, a fault is raised if the response from the target isn't 200 (success).

<PreFlow name="PreFlow">
    <Response>
        <Step>
            <Name>RaiseFault</Name>
            <Condition>(response.status.code GreaterThan "200")</Condition>
        </Step>
    </Response>
</PreFlow>

For more about error handling, see Handling faults.