Search code examples
apigee

How to use the same Flow for request and response for Apigee proxy?


For Apigee API proxy, I need to select a flow based on request parameter. But I also need to remove that parameter before sending the request to the target.

I tried doing this:

  <Flow name="SpecialFlow">
    <Condition>request.queryparam.specialKey != null</Condition>
    <Request>
      <Step>
        <Name>removeSpecialKey</Name>
      </Step>
    </Request>
    <Response>
      <Step><Name>doSpecialStuff</Name></Step>
    </Response>
  </Flow>

However, since specialKey is removed, the response step doSpecialStuff never gets called. How do I make sure the same flow is used for both request and response in this case?

I remove the parameter like:

context.removeVariable('request.queryparam.specialKey');

Solution

  • Great question and a common scenario. In my proxies I use one of two strategies.

    In the first I a saveVars policy right before I head to the target flow, typically as the last step in the preflow request. That policy looks like this:

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
        <AssignMessage async="false" continueOnError="true" enabled="true" name="assignSaveMessage">
            <DisplayName>assignSaveMessage</DisplayName>
            <AssignVariable>
                <Name>save.request.verb</Name>
                <Ref>request.verb</Ref>
            </AssignVariable>
            <AssignVariable>
                <Name>save.request.queryparam.content</Name>
                <Ref>request.queryparam.content</Ref>
            </AssignVariable>
            <AssignVariable>
                <Name>save.request.content</Name>
                <Ref>request.content</Ref>
            </AssignVariable>
            <AssignVariable>
                <Name>save.request.queryparam.propagation</Name>
                <Ref>request.queryparam.propagation</Ref>
            </AssignVariable>
            <IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
            <AssignTo createNew="false" transport="http" type="request"/>
    </AssignMessage>
    

    I then execute a restoreVars policy in the first step of postFlow response. This way I can use those variables as conditions. Here is the restore policy:

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <AssignMessage async="false" continueOnError="true" enabled="true" name="assignRestoreMessage">
        <DisplayName>assignRestoreMessage</DisplayName>
        <AssignVariable>
            <Name>request.verb</Name>
            <Ref>save.request.verb</Ref>
        </AssignVariable>
        <AssignVariable>
            <Name>request.queryparam.content</Name>
            <Ref>save.request.queryparam.content</Ref>
        </AssignVariable>
        <AssignVariable>
            <Name>request.queryparam.propagation</Name>
            <Ref>save.request.queryparam.propagation</Ref>
        </AssignVariable>
        <IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
        <AssignTo createNew="false" transport="http" type="request"/>
    </AssignMessage>
    

    In your case, you would "stash" your queryparam right before you remove it as a queryparam.

    The second approach is to simply assign the request param into another variable, a custom labelled variable that can be accessed throughout the flow. The only concern with this approach is the source of these copied variables is not obvious later flows.