This tutorial shows how to create a serverless API with DynamoDB using Claudia API Builder.
Prerequisites
- AWS account with access to IAM, Lambda and API Gateway
- Node.js 6
- NPM
- Claudia 2.6.0 or later
- Claudia API Builder 2.4.0 or later
The goal is to show how to create a serverless Node.js app with DynamoDB that stores and retrieves data. This service will be for an ice cream shop. You will save and show ice creams.
1. Serverless host setup — AWS
You need to have an AWS account with a locally set AWS credentials file, and installed Claudia.js .
If you don’t have it, please go through Installing and Configuring Claudia.js.
2. Write your service — Ice Cream Shop
Create your project folder (you can name it ice-cream-shop
) and open it in your terminal.
Initialize your Node project.
You can do it quickly by running npm init -f
Then run
npm install aws-sdk claudia-api-builder -S
This installs AWS SDK and Claudia API Builder. You need AWS SDK for accessing DynamoDB. Claudia API Builder is a helper tool with an Express-like syntax for your endpoints.
Your service needs to have two endpoints:
-
to save an icecream — needs a POST request
-
to get all saved ice creams — needs a GET request
Now create an empty index.js file. Open it and type:
const ApiBuilder = require('claudia-api-builder'),
AWS = require('aws-sdk');
var api = new ApiBuilder(),
dynamoDb = new AWS.DynamoDB.DocumentClient();
api.post('/icecreams', function (request) { // SAVE your icecream
var params = {
TableName: 'icecreams',
Item: {
icecreamid: request.body.icecreamId,
name: request.body.name // your icecream name
}
}
return dynamoDb.put(params).promise(); // returns dynamo result
}, { success: 201 }); // returns HTTP status 201 - Created if successful
api.get('/icecreams', function (request) { // GET all users
return dynamoDb.scan({ TableName: 'icecreams' }).promise()
.then(response => response.Items)
});
module.exports = api;
This finishes your service.
3. Database — setup DynamoDB
You need to create a database on AWS, but instead of using AWS Console, you can just execute one command:
aws dynamodb create-table --table-name icecreams \
--attribute-definitions AttributeName=icecreamid,AttributeType=S \
--key-schema AttributeName=icecreamid,KeyType=HASH \
--provisioned-throughput ReadCapacityUnits=1,WriteCapacityUnits=1 \
--region us-east-1 \
--query TableDescription.TableArn --output text
This command creates a DynamoDB table named icecreams
in the same region as our Lambda, with an key attribute icecreamid
of String type. The command returns the table’s Amazon Resource Name (ARN) to confirm that everything is set up correctly.
Giving your service permission for the database
The last step is allowing your service access to your DynamoDb database. To do that your service requires a permission policy. Instead of doing it via AWS Console, you can create a policy file in your project and apply it with Claudia.
Inside your ice-cream-shop project folder create a folder named policy
and in it a file called dynamodb-policy.json
with the following contents:
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"dynamodb:DeleteItem",
"dynamodb:GetItem",
"dynamodb:PutItem",
"dynamodb:Scan"
],
"Effect": "Allow",
"Resource": "*"
}
]
}
This policy allows your Lambda service to access your DynamoDb database. When invoking Claudia to deploy your code, this policy file location needs to be passed as the command option, to let Claudia know to assign the policy to your Lambda.
It’s time for your first deployment. In the first, Claudia.js creates a Lambda for your service. So, go back to your project folder ice-cream-shop
and run:
claudia create --region us-east-1 --api-module index --policies policy
This command creates your serverless container (AWS Lambda) in the us-east-1
region, sets the index
file as the main, and assigns the policy from the policy
folder to your Lambda. If successful, it returns the created service URL endpoint in the command final output similar to this:
{
"lambda": {
"role": "ice-cream-shop-executor",
"name": "ice-cream-shop",
"region": "us-east-1"
},
"api": {
"id": "your-service-id",
"module": "index",
"url": "https://your-service-url.execute-api.us-east-1.amazonaws.com/latest"
}
}
That’s it!
Trying out your service
Use cURL for testing. Get all ice creams:
curl https://your-service-url.execute-api.us-east-1.amazonaws.com/latest/icecreams
Save an ice cream:
curl -H "Content-Type: application/json" -X POST \
-d '{"icecreamId":"123", "name":"chocolate"}' \
https://your-service-url.execute-api.us-east-1.amazonaws.com/latest/icecreams
By running these commands you’ll see your service working!
That’s it!
Errors?
In case of an error, please check your code if you haven’t missed anything. After an error, invoking the command again may show
'Role with name ice-cream-shop-executor already exists.'
In that case, go to your AWS Console IAM, in the left bar click Roles
and find a role with the name error specified and delete it. Then try the previous claudia create command again.
Updating your service
If you want to redeploy to your Lambda with Claudia.js, now you need to do a claudia update instead of create . The full command would look like this:
claudia update
It doesn’t need all those configuration options like create
, because it stores them locally for you. If its successful, it also returns the URL of your deployed service.
Now go, you deserve some ice cream!