Sharedflow dynamic conditional string not working in default xml

Hi Team,

I have requirement to read multiple API proxies names and that includes request path with comma (“,”) separated from keyvaule maps as metioned below

KVM name is SF-KVM and the key name is globalvar that contains a value

apiproxyname1,apiproxyname12,apiproxyname3,apiproxyname4,/apiproxyname1/sample/json2xml

I have used a KVM policy to retrieve value and written a java script policy to construct the conditional string to execute one of the policy based on condition in a shared flow default flow.

var kvalue=context.getVariable(“kvm-val”);
var conditionStr=“”;
var arr=“”;

if(kvalue.indexOf(‘,’) > -1) {
arr = kvalue.split(‘,’);
for(i=0; i<=arr.length-1; i++) {
if(arr[i].indexOf(‘/’) > -1 && arr[i].indexOf(‘/’) === 0) {
conditionStr+=“or” + " (request.path = " + arr[i].toString() + ") "
} else {
conditionStr+=“or” + " (apiproxy.name = " + arr[i].toString() + ") "
}
}
} else {
if(kvalue.indexOf(‘/’) > -1 && kvalue.indexOf(‘/’) === 0) {
conditionStr+=“or” + " (request.path = " + kvalue.toString() + ") "
} else {
conditionStr+=“or” + " (apiproxy.name = " + kvalue.toString() + “)”
}
}
}
context.setVariable(“condStr”,conditionStr);
print(conditionStr)

I am successfully able to construct the conditional string dynamically as mentioned below and is this possible to use dynamically constructed conditional string in an shared flow default

condStr= (apiproxy.name = apiproxyname1) or (apiproxy.name =apiproxyname2) or (apiproxy.name = apiproxyname3) or (apiproxy.name = apiproxyname4) or (request.path /apiproxyname1/sample/json2xml)

sharedflow default xml file content as mentioned below

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> kvm-policy KVM-javascript RaiseFault condStr this is step is not at all working

I have requirement to apply this shared flow on environment level using a flow-hook

I appreciate any help regarding this.

Regards
Nandeesha

1 Like

It is not possible to have a dynamic condition in Apigee DSL. You cannot do this:

<Step> 
  <Name>RaiseFault-1</Name>
  <Condition>variable-here</Condition> <!-- will not work -->
</Step>

Also, there is no ref= attribute on a Condition. You also cannot do this :

<Step> 
  <Name>RaiseFault-1</Name>
  <Condition ref='variable-here'/> <!-- will not work -->
</Step>

The condition expression needs to be static, and must follow the syntax outlined in the Condition reference.

If you want to have a “dynamic condition” then a good way to do it is to use the JavaScript policy, not to construct the string, but to evaluate the value and set a flag. For example

var kvalue = context.getVariable("kvm-val");
var result = false;
var requestPath = context.getVariable("request.path");
var proxyName = context.getVariable("apiproxy.name");

// split() will work whether there is a comma or not
kvalue.split(',')
  .forEach(function(item) {
    if ( ! result) {
      if (item.indexOf('/') === 0) {
        result = result || (requestPath === item);
      }
      else {
        result = result || (proxyName === item);
      }
    }
  });

context.setVariable('kvm_rules_matched', String(result)); // "true" or "false"

Then use it in a Condition:

<Condition>kvm_rules_matched = "true"</Condition>

If you want to use more functional idioms in your JS you can do this:

var kvalue = context.getVariable("kvm-val");
var requestPath = context.getVariable("request.path");
var proxyName = context.getVariable("apiproxy.name");
var result =
  kvalue
  .split(',')
  .find(function(item) {
    return ((item.indexOf('/') === 0)  && (requestPath === item)) ||
      ((item.indexOf('/') === -1) && (proxyName === item));
  });

context.setVariable('kvm_rules_matched', String(!!result)); // "true" or "false"

That feels more readable to me, but YMMV.