How To: Invoke lambda functions through WSO2 API Manager

Written by hashanbn | Published 2018/01/05
Tech Story Tags: aws-lambda | wso2 | api-management

TLDRvia the TL;DR App

AWS lambda is getting quite a buzz in the world of cloud computing these days. It takes the burden of managing infrastructure from the hands of the developers. Now you have to only worry about your code, you can just put your code into a set of lambda functions and then you are good to go. Unlike AWS EC2 instances, AWS lambda is an event driven system, which will only charge you for the time that your application is running. Hence, making it a cost effective & easy way of implementing the cloud backends.

How the invocation of an API happened in the traditional API management was, you have a backend server which is listening in for any requests that are coming in, and the API management layer will send a request to that backend server. Then once the backend server is done with the computation it will send out a response which will be received by the API management layer and serve that to the customer after necessary processing. However, in the case of AWS lambda there is no backend server that is listening in for the incoming requests, it’s an event based system. So how can we invoke a lambda function from WSO2 API Manager? I will explain two methods that can be used to invoke AWS lambda functions from WSO2 API manager in the sections below.

First of all, we need to create an AWS account, create the necessary lambda functions and obtain the credentials to invoke those. To do those preliminary steps please follow the getting started guide on AWS lambda.

Once you are done with the preliminary setup, the first method you can use to invoke lambda functions through API Manager is by running a simple nodejs application to invoke the lambda function for you. You can pass the config parameters such as region, access key id, secret key & etc. along with the payload, to the nodejs application. Then the nodejs application will invoke the lambda function using the “aws-sdk” library and provide the response. Please see the below diagram for this process.

In this method no changes need to be done to the API Manager. As with the traditional API management, the API manager will route the request to the nodejs endpoint and then nodejs will invoke the lambda function and send the response back. Please refer to [1] for a sample implementation of a nodejs application that can be used to invoke aws-lambda functions. After you deploy the nodejs application, you can put the url of the resource you want to send the data to in the nodejs application as the endpoint to the APIs.

If most of your services are running on AWS and you don’t mind getting a new EC2 instance to run the nodejs application, then this method is for you. Because it’s easy to implement and easier to manage since no configuration changes have been done to the API Management layer. However, having said that this is not for everybody. You might not be willing to pay that extra price to purchase the EC2 instance just to run a nodejs application to invoke lambda functions.

Since WSO2 products are highly customizable we still have a solution for you. What you can do is, instead of having a separate nodejs instance to invoke the lambda functions, we can use a class mediator in the WSO2 API Manager to invoke the lambda functions. I will not go into details of how to write a class mediator in this article since it’s not within the scope of this article. However, I will try to cover that topic in a different article. Anyhow, in this case we can engage the custom mediator in the in-sequence of the API Manager and disable the endpoints from the configurations. I specifically mentioned to disable the endpoints from the configurations because by default API Manager doesn’t allow you to publish an API using the swagger UI without specifying the production & sandbox endpoints. What you can do is you can give some dummy urls in the UI and then comment them out in the synapse config. Also to get the response out you have to put a respond mediator at the end of the in-sequence, otherwise it will not give the response back. Please see the below diagram for a visual overview of the architecture in this scenario.

API Manager uses Class Mediator to invoke aws-lambda using aws-sdk

One thing you have to keep in mind when writing this custom mediator is that, you have to pack the aws-sdk java library and the matching versions of the dependencies with the final package. Otherwise, you might run into issues with aws-sdk trying to use incompatible dependency versions from the WSO2 product pack. After the packaging is done you can drop the osgi bundle to the dropins folder in the product pack and it will work without any issues. Please refer to [2] for a sample implementation of a class mediator that can be used to invoke lambda functions from WSO2 API Manager. A sample API definition of an API invoking a lambda function through this class mediator would look as follows. Please note that the values used in the class properties are all dummy values.

<?xml version="1.0" encoding="UTF-8"?><api xmlns="http://ws.apache.org/ns/synapse"name="admin--test"context="/test/v1.0.0"version="v1.0.0"version-type="context"><resource methods="POST" url-mapping="/test" faultSequence="fault"><inSequence><property name="api.ut.backendRequestTime"expression="get-property('SYSTEM_TIME')"/>

     <class name="org.wso2.awsmediator.AWSClassMediator">  
         <property name="region" value="region"/>  
         <property name="functionName" value="function\_name"/>  
         <property name="accessKey" value="accesskey-value" />  
         <property name="secretKey" value="secret-key" />  
         <property name="maxConnections" value="1200"/>  
     </class>  
     <respond/>  
  </inSequence>  
  <outSequence>  
     <class name="org.wso2.carbon.apimgt.gateway.handlers.analytics.APIMgtResponseHandler"/>  
     <send/>  
  </outSequence>  

</resource><handlers><handler class="org.wso2.carbon.apimgt.gateway.handlers.common.APIMgtLatencyStatsHandler"/><handler class="org.wso2.carbon.apimgt.gateway.handlers.security.CORSRequestHandler"><property name="apiImplementationType" value="ENDPOINT"/></handler><handler class="org.wso2.carbon.apimgt.gateway.handlers.security.APIAuthenticationHandler"/><handler class="org.wso2.carbon.apimgt.gateway.handlers.throttling.ThrottleHandler"/><handler class="org.wso2.carbon.apimgt.gateway.handlers.analytics.APIMgtUsageHandler"/><handler class="org.wso2.carbon.apimgt.gateway.handlers.analytics.APIMgtGoogleAnalyticsTrackingHandler"><property name="configKey" value="gov:/apimgt/statistics/ga-config.xml"/></handler><handler class="org.wso2.carbon.apimgt.gateway.handlers.ext.APIManagerExtensionHandler"/></handlers></api>

I hope this article was helpful in understanding how to use lambda functions as backends to the APIs in WSO2 API manager. If there are any questions or if you run into any problems while trying this out, please post them in the comments section. I will try and answer all the questions as soon as possible. If you think this article is helpful don’t forget to clap for it, that will make it easier for others to find it :).

[1] https://github.com/hashanbn/nodejs_lambda

[2] https://github.com/hashanbn/AWSLambdaClassMediatorWSO2


Published by HackerNoon on 2018/01/05