EDUCAÇÃO E TECNOLOGIA

SAPAPIM – Guide to create single API Proxy with multiple Target End Point and capability to change the target URI during execution

SAPAPIM – Guide to create single API Proxy with multiple Target End Point and capability to change the target URI during execution

Applies to:  

SAP Business Technology Platform: SAP API Management

Summary

This document provides step by step guidance on how to implement a single API proxy with multiple target end point along with capability to change the target URI during execution with SAP API Management in SAP BTP.

In our case the API proxy implementation sample is called “MULTIROUTE_PROXY_API”.

Author: Sambaran Chakraborty

Company: IBM

Created on 18 November 2021

Business Scenario

In this tutorial we will realize the two very common business scenarios which we face in our day-to-day work.

  • Need to have a single API proxy which can connect to multiple backend system based on certain condition.
  • Need to have the capability to update the target proxy path during runtime.

Step1:

Create two API provider pointing to 2 different backend system

Cockpit->Services->API Management >Access API Portal->Configure->API Providers>Create MYUSERDB_1: Employee User Store

MYUSERDB_2: Customer User Store

Step2:

Crate API proxy ““MULTIROUTE_PROXY_API”

API Portal -> Develop->Create

Select any one of the providers we created earlier

*Note we have selected URL=”/” as rest of the path we will set during execution

Save API Proxy URL: https://<host>.apimanagement.eu2.hana.ondemand.com/multiroute_proxy

Step3:

Now will add the capability to connect to another API provider

Export the API Proxy into your local system
Open the .zip file APITargetEndPoint ->default.xml

Crate a copy and rename both the XML file as “myuserdb1.xml” “myuserdb2.xml”

Update <name>, <provider_id>, <isDefault> tags in each file as shown

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<TargetEndPoint xmlns="http://www.sap.com/apimgmt"> <name>myuserdb1</name> <provider_id>MYUSERDB_1</provider_id> <additionalAPIProviders/> <isDefault>true</isDefault> <relativePath>/</relativePath> <properties/> <faultRules/> <preFlow> <name>PreFlow</name> </preFlow> <postFlow> <name>PostFlow</name> </postFlow> <conditionalFlows/> <loadBalancerConfigurations> <isRetry>false</isRetry> <healthMonitor> <isEnabled>false</isEnabled> </healthMonitor> </loadBalancerConfigurations>
</TargetEndPoint>

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<TargetEndPoint xmlns="http://www.sap.com/apimgmt"> <name>myuserdb2</name> <provider_id>MYUSERDB_2</provider_id> <additionalAPIProviders/> <isDefault>false</isDefault> <relativePath>/</relativePath> <properties/> <faultRules/> <preFlow> <name>PreFlow</name> </preFlow> <postFlow> <name>PostFlow</name> </postFlow> <conditionalFlows/> <loadBalancerConfigurations> <isRetry>false</isRetry> <healthMonitor> <isEnabled>false</isEnabled> </healthMonitor> </loadBalancerConfigurations>
</TargetEndPoint>

Now Open the APIProxyEndpoint->default.xml

Update <routeRules> as shown

*This will let us point to different target based on condition

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ProxyEndPoint default="true" xmlns="http://www.sap.com/apimgmt"> <name>default</name> <base_path>/multiroute_proxy</base_path> <properties/> <routeRules> <routeRule> <name>myuserdb2</name> <conditions>queryinfo.userdb = "userdb2"</conditions> <targetEndPointName>myuserdb2</targetEndPointName> <sequence>1</sequence> <faultRules/> </routeRule> <routeRule> <name>myuserdb1</name> <conditions>queryinfo.userdb = "userdb1"</conditions> <targetEndPointName>myuserdb1</targetEndPointName> <sequence>2</sequence> <faultRules/> </routeRule> </routeRules> <faultRules/> <preFlow> <name>PreFlow</name> </preFlow> <postFlow> <name>PostFlow</name> </postFlow> <conditionalFlows/>
</ProxyEndPoint>

Import the modified .zip

API Portal-> Import -> MULTIROUTE_PROXY_API.zip

Open the proxy and check the new route

Now add a policy to accept the query parameter “userdb” from consumer/client application

Go to Policies -> ProxyEndpoint -> Preflow   and add the policy as shown

<ExtractVariables async="true" continueOnError="false" enabled="true" xmlns='http://www.sap.com/apimgmt'> <Source>request</Source> <QueryParam name="userdb"> <Pattern ignoreCase="true">{userdb}</Pattern> </QueryParam> <VariablePrefix>queryinfo</VariablePrefix> <IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
</ExtractVariables>

Step4:

Add logic to dynamically add proxy path during execution

API Proxy->Target Endpoint->URL

Policy Editor- > Target Endpoint-> PreFlow Create a JavaScript policy  as shown

<!-- this policy allows us to execute java script code during execution of an API Proxy -->
<Javascript async="false" continueOnError="false" enabled="true" timeLimit="200" xmlns='http://www.sap.com/apimgmt'> <!-- contains reference to any library scripts that help the main code file --> <!-- contains the name of the main code file --> <ResourceURL>jsc://setTargetPath.js</ResourceURL>
</Javascript> 

Create setTargetPath.js file and add code as shown

//Add your target path . You can retrive it from external config or based on any condition
//For this example as its same for both the API provider , we are putting it directly var target_path = ""; if (context.getVariable('request.queryparam.userdb') === 'userdb1') { target_path = "service/scim/" ; }else if (context.getVariable('request.queryparam.userdb') === 'userdb2'){ target_path = "service/scim/"
} context.setVariable("target.copy.pathsuffix", true);
context.setVariable('target_path', target_path); 

Now Export the project and update “myuserdb2.xml”<relativePath> tag with “target_path” variable  as shown

Import the updated .zip file to API management

Save and Deploy

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<TargetEndPoint xmlns="http://www.sap.com/apimgmt"> <name>myuserdb2</name> <provider_id>MYUSERDB_2</provider_id> <additionalAPIProviders/> <isDefault>false</isDefault> <relativePath>/{target_path}</relativePath> <properties/> <faultRules/> <preFlow> <name>PreFlow</name> <request> <isRequest>true</isRequest> <steps> <step> <policy_name>setTargetPath</policy_name> <condition> </condition> <sequence>1</sequence> </step> </steps> </request> </preFlow> <postFlow> <name>PostFlow</name> </postFlow> <conditionalFlows/> <loadBalancerConfigurations> <isRetry>false</isRetry> <healthMonitor> <isEnabled>false</isEnabled> </healthMonitor> </loadBalancerConfigurations>
</TargetEndPoint>

Step5:

Now we are ready to test API

We will use POSTMAN here as client and the same can be done by any client application (UI)

Scenario 1: Get employee information from “MYUSERDB_1

*Here I am using Basic Authentication to connect to backend

Result: Successfully routed to employee user backend with valid target path and retrieved data

Scenario 2: Get customer information from “MYUSERDB_2”

Result: Successfully routed to customer user backend with valid target path and retrieved data

Scenario 3: Get customer information from “MYUSERDB_1

Result: Successfully routed to employee user backend with valid target path but no result as the queried customer id does not present into that system.

Scenario 4: Get employee information from “MYUSERDB_2”

Result: Successfully routed to customer user backend with valid target path but no result as the queried employee id does not present into that system.

Conclusion:

With this exercise we are able to  use single API proxy to connect to multiple backend system based on conditional statement and dynamically change the target path during execution.

—————————————-HAPPY CODING——————————————————-

Reference : Enable Dynamic Routing