How to Build HTTP API using AWS Serverless Application Model (SAM), AWS Lambda and Node.js
Tags: aws, serverless, cloudcomputing, node
Published: 2023-04-24 08:30:56

 
**AWS Serverless Application Model(SAM)** provides short hand syntax to specify serverless resources such as lambda functions, API Gateway and dynamodb. The syntax can be used to model the application you want create in AWS using yaml.
**AWS Lambda** is a serverless, event-driven service that runs your code on demand.


- In this article we are going to **develop** a HTTP API locally with AWS SAM, **deploy** it to AWS and **test** the deployed API.

## Table of Contents
- [Create Lambda Function](#create-lambda-function)
- [API Gateway](#api-gateway)
- [HTTP API AWS SAM on VS Code](#http-api-aws-sam-on-vs-code)
- [Deploying to AWS](#deploying-to-aws)
- [Testing](#testing)
- [CloudWatch Logs](#cloudwatch-logs)
- [Conclusion](#conclusion)

## Create Lambda Function.
- Search for Lambda on the search bar, on the left side bar click on **Functions** then on Create Function.
- Provide the needed details i.e Function name, runtime and architecture, then **create  function**.

_Use image for referral_
![create lambda](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1je6lrpgnhh3kobc5d1d.png)


## API Gateway
- This is a fully managed service that makes it easy for developers to create, deploy, and manage APIs at any scale.
- On the page click on _API_ so as to pick on the API you want to create.(We are building HTTP API)

_Use image for reference_
![build http](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/e4pqtuoe5mfaw3vj1130.png)

- Once you click on _build_:-

**Step 1** - Add an Integration which will be Lambda, select the AWS and select the lambda function you created earlier. Provide an API name.
![Intergration](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5w8rqq69axk051c7t62f.png)

**Step 2** - We shall **Configure routes** select a **GET** method and provide a resource path and the Intergration target is the lambda function we created.
![config](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/327hup1ogb15u4z4v57d.png)

**Step 3** - Stages is the deployment environment where our API is going to be hosted. leave it to **default** and ensure that **auto-deploy** is activated, it comes in handy.
**Step 4** - Review everything you have done and click on **create** if you are satisfied with it.

## HTTP API AWS SAM on VS Code
###Prerequisites

1. 
 Ensure you have an AWS account.

2. 
 Install **AWS CLI** using this [link](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/install-sam-cli.html).
- Configure your AWS using the `aws configure` where you'll be needed to provide your AWS Key details.
In case you want to generate new ones use this [link](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/prerequisites.html#prerequisites-configure-credentials) to generate new ones.

3. 
 Install the **AWS SAM CLI** using this [documentation](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/install-sam-cli.html).

4. 
 Install Docker [here] (https://docs.docker.com/engine/install/) (Local Testing)

5. Install Nodejs [here](https://nodejs.org/en) 

6. Install AWS Toolkit VS Code Extension.
7. Install Thunder Client CLI extension on VS Code.



### Create SAM project
- Create a folder and open it in VS Code. 
- Generate a default sam application using `sam init`. Pick on _AWS Quick Start application template_.  _Hello world Example_, _nodejs14.x_ runtime and package type, _zip_ package,  _Hello World Example_ starter template, _N_ to x-ray tracing to avoid extra charges finally give your sam project a name.

- A folder with the sam project name will be generated, let's discuss it in details:-
`events/`: contains sample events that can be used for local testing of Lambda functions.
- `hello-world/`: contains an example AWS SAM app that is used to test that everything is working correctly.
- `.gitignore`: used by git to determine which files and directories to ignore when committing changes to a repository.
- `README.md`: a markdown file that contains documentation for the project.
- `samconfig.toml`: a configuration file used by the SAM CLI to specify options and settings for deploying the application.
- `template.yaml`: defines the resources and configuration for the application.

###Template.yaml Code Explanation
- Check out the full code in `template.yaml` [here](https://github.com/IvyJeptoo/AWS-SAM-Nodejs/blob/master/template.yaml).
Under the **Resources** section, `HttpApi` defines the resources that are going to be created on AWS.
We've kept our default HelloWorldFunction that has a type of serverless function
There are three **events**:

1. **GetUsers**: Gets all the users from the API.
Has type _HttpApi_,  path of _/user_, method used is _get_, ApiId with a ref of _HttpApi_

**Note**
**ApiId Ref(HttpApi) is defined above the HelloWorldFunction and has a type of serverless HttpApi with a stage name of nonprod(default)**

2. **GetUser**:
Gets a single user by id from the the API.
Has type _HttpApi_,  path of _/user/{id}_, method used is _get_, ApiId with a ref of _HttpApi_

3. **PostUser**
Creates a new user.
Has type _HttpApi_,  path of _/user_, method used is _post_, ApiId with a ref of _HttpApi_


### app.js Code Explanation
- Check out the full code in `app.js` [here](https://github.com/IvyJeptoo/AWS-SAM-Nodejs/blob/master/hello-world/app.js). 
- This file defines the lambda handler i.e the code that will run when our lambda is invoked.
`Response` is the object we get back from the lambda(API Response)
`const USERS` is an array of objects that contain 
the users it has a property of name and userid.
`lambdaHandler` has event and context passed in. In the event is where the http request will be injected 
`console.log` the event to get the http in cloudwatch logs.
`result` will be passed in the response object.
- **First condition** uses the event object passed in earlier and the routeKey(has the method used) 
Query parameters can be passed in for start and end(default for start is 0 and total array length for the end.)
**Validation**
- _first validation_ is to ensure the start is greater or equal to 0.
- _second validation_ is to ensure the end is less or equal to the array length.
- _third validation_ ensures the start is less than end.
- **Second Condition** we have the POST method and /user path where we will post new users to the user array
- **Third Condition** returns a single user using the method get and path of /user/{id} with a personalized greeting.


## Deploying to AWS

- Ensure you are in the directory that contains `template.yaml`.

- Run `sam build` command to build the Lambda function and generate a deployment package.
aws-sam folder will be generated successfully.

**N/B**
**Verify that your IAM user has the necessary permissions to perform the deployment. The required permissions are:**
- **AWSLambdaFullAccess**
- **IAMFullAccess**
- **AmazonAPIGatewayAdministrator**
- **AmazonS3FullAccess**
- **CloudFormationFullAccess**
- **CloudWatchLogsFullAccess**





- Run `sam deploy --guided` for step by step creation of CloudFormation stack using the SAM template and Lambda function code. 
Provide a name for the app, use the default region, confirm the changes,allow IAM role creation, don't disable rollback, we do not have authorization so agree to it, we want our arguments saved in the configuration file and use default for the rest.
Confirm that we want to deploy the changes(it should be successful).

- On your AWS account under **API Gateway** you will see the just created HttpApi once you refresh it.

_HttpAPi overview_
![http](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x3wg1m87wyqwao45nc12.png)

- Under the **routes** section we can also see the paths we created as so:

![Routes](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9xuy6aga8ozg17d01e23.png)

- All the routes have a configuration integration(same Lambda) as so:
![config](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x6xz47s4db1j1iomcamf.png)

- Copy the stages copy the Invoke URL which we will use it for testing.
![url](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qdcvrb1lupmwz035mfp2.png)


## Testing

- We will use **Thunder Client CLI** extension for testing our API

_GetUsers_
We are doing a get request and the response will be all the users in our API.
To test the query string you can add the specifications at the end `/user?start=1&end=3`.
![users](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lpurvvq0zlqz3bees521.png)

_GetUser_
This is also a get request with id specification the response is a personalized greeting with the user's name.
![user](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nw4q5n9t95ltxteodflb.png)

_postUser_
Using the post methos it adds a new user to the user array. 
![post user](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9pby6p5o7rcwz16utmpa.png)

## CloudWatch Logs

- Earlier we printed the events to the logs in CloudWatch.
- Once in cloudwatch go to log groups then find the correct log group then click on it.
- You will see an overview of it then at the bottom there is log streams which has all the calls made.
- The log has START, END and a REPORT like so:

![LOGS](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vjgnmtwd41p177x0lsfp.png)


## Conclusion
AWS Serverless Application Model (SAM), AWS Lambda and Node.js  make building APIs a breeze. With the steps outlined in this article, you can get started with your own simple API endpoint in no time. If you found this article helpful, be sure to connect with me and leave your comments and feedback. Happy coding!