In order to test a Lambda function that we created, click the AWS Resources tab on the right hand sidebar of the Cloud9 environment. Then right click the function that you want to test, Run and then choose either of the four options.

aws-cloud9-lambda-apigateway-22

We will go one by one on all of them:

Testing Lambda Functions

Run Lambda Local

This mode is for testing the changes that you yet have only in your local environment have not deployed yet to Lambda. Clicking the Run Local from the list of options shown above will bring the following screen:

aws-cloud9-lambda-apigateway-23

We will keep the sample payload empty at this time. Click Run:

aws-cloud9-lambda-apigateway-26

We will see the following execution results:

aws-cloud9-lambda-apigateway-28

The run was successful but the result is null, because we have not returned anything.

Let’s add a response to return back from the local Lambda function as JSON. Open the index.js file and replace all the code with the following:


exports.handler = (event, context, callback) => {
    let responseBody = {
        messageFromCommandCenter : 'Ignition Sequence Start'
    };

    callback(null, responseBody);
};

The thing to note here is that the callback() function now has 2 parameters, first is null and the second is a JSON string; it is best to use JSON objects to return as they can also be used if there is API Gateway integration. But we can return any kind of object as far as only Lambda functions are concerned.

Also, whatever object we want to return from a Lambda function, we will always place it as the second parameter in the callback() function.

Now let us run the Lambda function again and see the results:

aws-cloud9-lambda-apigateway-29

You can see the JSON string as the response from the function.

You can debug the application by clicking the grey bug button next to the Run button:

aws-cloud9-lambda-apigateway-34

And adding a breakpoint to a line in the index.js file:

aws-cloud9-lambda-apigateway-35

When you click Run, debugging will commence and the breakpoint will be hit.

Passing Input Parameters

In case you want to pass parameters, you can do so by supplying a payload(in JSON format):

aws-cloud9-lambda-apigateway-31

The payload parameters are accessible via the event parameter in the exports.callback handler. Replace the code in index.js with the following:


exports.handler = (event, context, callback) => {
    let responseBody = {
        messageFromCommandCenter : event.CommandCenter
    };

    callback(null, responseBody);
};

If you debug the application and check the contents of the event parameter, you can see the following:

aws-cloud9-lambda-apigateway-36

Now to see it actually works, let’s run the function and see the response:

AWS-Cloud9-Lambda-ApiGateway-33.png

As we can see, the message has been updated as per the parameter provided to the Lambda function.

Run Lambda Remote

 

The only difference between running a Lambda function locally or remote is that local is on our environment, whereas remote has been deployed on AWS Lambda. In the case of testing from Cloud9, there is no difference in the syntactics. Just Go to AWS Resoruces > right click the desired function > Run Run Remote.

Or from the test screen, choose from the drop down list:

aws-cloud9-lambda-apigateway-30

You can check out how to deploy Lambda functions here.

Testing with API Gateway requests

Next option in the dropdown list is API Gateway Local.

aws-cloud9-lambda-apigateway-41

If you followed this tutorial, you will notice that while creating Lambda function, we created a Lambda-API Gateway integration.

The concept of local vs remote in APPI Gateway as well remains the same, But the format of passing input parameters and returning values becomes different.

Passing Input Parameters

Passing input parameters is a bit different when the Lambda function is called from the API Gateway. Let’s see how. If you do a POST request and debug the application and see the contents of the event parameters, they are a bit different:

aws-cloud9-lambda-apigateway-38

As we can see, the event parameter is shaped differently in the case of a call from the API Gateway. So how do we have the same function as serve it directly to Lambda as well as API Gateway at the same time?

The answer is that in the case of API Gateway, we extract the values from the event’s body property and assign them directly to the event object. Replace the code in the index.js file with the following:

</pre>
<div class="line number1 index0 alt2"><code class="jscript plain">exports.handler = (event, context, callback) =&gt; {</code></div>
<div class="line number2 index1 alt1" style="padding-left:30px;"><code class="jscript keyword">if</code> <code class="jscript plain">(event.body) {</code></div>
<div class="line number3 index2 alt2" style="padding-left:60px;"><code class="jscript keyword">let</code> <code class="jscript plain">requestBody = JSON.parse(event.body);</code></div>
<div class="line number4 index3 alt1" style="padding-left:60px;"><code class="jscript plain">event.CommandCenter = requestBody.CommandCenter;</code></div>
<div class="line number5 index4 alt2" style="padding-left:30px;"><code class="jscript plain">}</code></div>
<div class="line number6 index5 alt1" style="padding-left:30px;"></div>
<div class="line number7 index6 alt2" style="padding-left:30px;"><code class="jscript keyword">let</code> <code class="jscript plain">responseBody = {</code></div>
<div class="line number8 index7 alt1" style="padding-left:60px;"><code class="jscript plain">messageFromCommandCenter : event.CommandCenter</code></div>
<div class="line number9 index8 alt2" style="padding-left:30px;"><code class="jscript plain">};</code></div>
<div class="line number10 index9 alt1" style="padding-left:30px;"></div>
<div class="line number11 index10 alt2" style="padding-left:30px;"><code class="jscript plain">callback(</code><code class="jscript keyword">null</code><code class="jscript plain">, responseBody);</code></div>
<div class="line number12 index11 alt1"><code class="jscript plain">};</code></div>
<pre>

In the above code, we check if the body is present in event(that means it’s a call from API Gateway, otherwise it’s from Lambda). If so, we are retrieving the body object from the event and assigning to a local variable requestBody, and then assigning the values of the requestBody object directly to the event object. This way, if it is an API Gateway request we parse the body and assign values to the event object, and if it is a Lambda request then we do nothing as the values are assigned to the event object already.

Running the API gateway request will now result in the following response:

aws-cloud9-lambda-apigateway-39

But we are receiving an Internal Server Error when we make an API Gateway request in Cloud9 to the Lambda function.

The reason behind that is that API Gateway requests expect a response that is in the form of an HTTP response. Our response must be an object that contains a <code>statusCode</code>, <code>body</code> and <code>header></code>. To do that, change the code in the index.js file to the following:


exports.handler = (event, context, callback) => {
    if (event.body) {
        let requestBody = JSON.parse(event.body);
        event.CommandCenter = requestBody.CommandCenter;
    }

    let responseBody = {
        messageFromCommandCenter : event.CommandCenter
    };

    let response = {
        statusCode: 200,
        body: JSON.stringify(responseBody),
        headers:{ 'Access-Control-Allow-Origin' : '*' }
    };

    callback(null, response);
};

Notice the response variable that contains the aforementioned fields. Run again and you will see the following response:

aws-cloud9-lambda-apigateway-40

We are now able to successfully retrieve the response in the case of API Gateway requests. This explains the difference in handling input parameters and returning response in the case of Lambda and API Gateway requests.

We will learn how to deploy Lambda functions in the next post.