Skip to Content
Technical Articles
Author's profile photo Sambaran Chakraborty

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

Assigned Tags

      4 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Michael-Peter Liermann
      Michael-Peter Liermann

      I've already used this approach. There is one very big drawback, however. Target policies that are edited in the UI are only changed for the default target endpoint, not for the other target endpoints.

      Author's profile photo Sudhir Yesu
      Sudhir Yesu

      Hi Sambaran,

      In step#3, have you edited the files without extracting them ? I tried extracting, editing, and compressing to .zip. But getting "Unable to create API Proxy; Contents in the zip file is invalid." while importing. Please assist.

      Thanks,

      Sudhir Yesu

      Author's profile photo Soura Gopal Sethy
      Soura Gopal Sethy
      Hello Sudhir,
      Make changes to the file without extracting them and save them before importing.

      Thanks,

      Souragopal

      Author's profile photo Lineker Tomazeli
      Lineker Tomazeli

      How can we keep proxy definitions and policies on source control and update API Manager as part of CI/CD ?