How To Add AWS Dynamodb Database To A Static Website Hosted In Amazon S3? – A Step-by-step Guide!

I have a static website thecloudadvisory. This website is designed in HTML, JavaScript & CSS, so it’s completely a static website. Due to its static nature, I have deployed this application in Amazon S3 and used the host static website feature, costing me nearly zero cents.

Off lately, I realized it’s good to have a contact page on the website to collect queries from customers/website visitors. 

A problem with adding server-side logic to static websites.

There are many ways to publish a static website for free. You can use free hosting like Github Pages, Firebase, Cloudflare, etc. 

Do you know what static means?  

A static website only uses HTML, CSS, and JavaScript. It doesn’t have server-side logic like PHP, Java, etc. Static websites can’t generate dynamic content. So you can’t save information to a database or send an email.

Now, the biggest problem with the static website deploying on the server is that it does not make sense to have a server running all the time when you don’t know when a user will contact you.

As you understand serverless, these architectures are useful when you want to add server-side logic to static websites and allow you to run the server-side scripts only when you need them.

For example, AWS Lambda only charges you based on the number of requests for your function and the time your code executes. So you’re not charged while waiting for visitors to contact you.

So I have decided to develop this website further and add a contact form with AWS Lambda(Serverless Architecture).

Following is the architecture flow with detailed guidance.

In the above diagram, the visitor/customer submits an inquiry through a “contact us” form that is hosted in an Amazon Simple Storage (S3) Service bucket as a static website. Information will flow in three simple steps:

1. The user will fill in and submit details in the “Contact us” form. Once the user submits the form, it will post the collected information to the Amazon API Gateway Restful service.

2. Then, the Amazon API Gateway service will pass collected user information to an AWS lambda function. You can use any supported programming language like Node.js, C#, Java, and Python.


3. AWS Lambda function will extract all information, auto-generate an email and forward it to your e-mail server using Amazon SES.

This is all we achieved in the blog ‘How to add Dynamic Contact Forms for S3 Static Websites Using AWS Lambda, API Gateway & Amazon SES – A step-by-step guide!’. Now, what about if we want to save this data to our database for the future?

Let’s look at the new architecture:

In this architecture, when a client accesses your HTTP API, it will be invoked through API Gateway, which routes the request to your Lambda function. In the Lambda function, we have all code that will interact with DynamoDB and return a response to API Gateway. And finally, API Gateway then returns a response to clients.

Create a DynamoDB table

From Architecture, we understand that all data received from the client will be stored in Amazon Dynamodb, so that we can retrieve the data later.

Let’s quickly understand what Amazon DynamoDB is.

Amazon DynamoDB is a fully managed AWS NoSQL database service. It provides fast and predictable performance with seamless scalability. It means, DynamoDB scales the resources dedicated to a table to hundreds or even thousands of servers that spread over multiple Availability Zones to meet your storage and throughput requirements.

Amazon DynamoDB is a good service to offload the administrative burdens of operating and scaling a distributed database so that you don’t have to worry about hardware provisioning, setup, configuration, replication, software patching, or cluster scaling.  

  1. To create a DynamoDB table, let’s open the DynamoDB console. Then Choose “Create table.” 
  1. For the Table name, enter contact details, For the Partition key, enter email and choose to Create.

It will redirect to the DynamoDB dashboard again, and you will be greeted with a message, “The contact-details table was created successfully.”

Create a Lambda function

We have created a DynamoDB table with a partition key. Now let’s create the Lambda function. 

As we know, Lambda functions will use Dynamodb SDK and store data in a table. 

So, we will create a Lambda function for the backend of our API. This Lambda function will do all CRUD (creates, reads, updates, and deletes) operations on DynamoDB. 

This Lambda function will use events from API Gateway to determine how to interact with DynamoDB based on the event type.

  1. Sign in to the Lambda console and Choose to Create function.
  1. Use store-contact-details as function name and select Node.js for run time.
  1. Under Permissions choose Change default execution role and Select Create a new role from AWS policy templates. For Role name, enter contact-crud-role.

For Policy templates, choose Simple microservice permissions. This policy grants the Lambda function permission to interact with DynamoDB. Then Choose Create function.

  1. Now open the index.js in the console’s code editor, and replace its contents with the following code. Choose Deploy to update your function.

const AWS = require(“aws-sdk”);

const dynamo = new AWS.DynamoDB.DocumentClient();

exports.handler = async (event, context) => {

  let body;

  let statusCode = 200;

  const headers = {

    “Content-Type”: “application/json”

  };

  try {

    switch (event.routeKey) {

      case “DELETE /items/{email}”:

        await dynamo

          .delete({

            TableName: “contact-details”,

            Key: {

              email: event.pathParameters.email

            }

          })

          .promise();

        body = `Deleted item ${event.pathParameters.email}`;

        break;

      case “GET /items/{email}”:

        body = await dynamo

          .get({

            TableName: “contact-details”,

            Key: {

              email: event.pathParameters.email

            }

          })

          .promise();

        break;

      case “GET /items”:

        body = await dynamo.scan({ TableName: “contact-details” }).promise();

        break;

      case “PUT /items”:

        let requestJSON = JSON.parse(event.body);

        await dynamo

          .put({

            TableName: “contact-details”,

            Item: {

              email: requestJSON.email,

              message: requestJSON.message,

              name: requestJSON.name

            }

          })

          .promise();

        body = `Put item ${requestJSON.email}`;

        break;

      default:

        throw new Error(`Unsupported route: “${event.routeKey}”`);

    }

  } catch (err) {

    statusCode = 400;

    body = err.message;

  } finally {

    body = JSON.stringify(body);

  }

  return {

    statusCode,

    body,

    headers

  };

};

Create an HTTP API

Now, let’s create an HTTP API endpoint. This HTTP endpoint will provide an endpoint to the Lambda function. 

We will also configure routes and integrations to connect with API and Lambda function.

  1.  Go to the API Gateway console, Choose to Create API, and then for HTTP API, choose Build.
  1. Now enter the API name contact-crud-api and Choose Next. For Configure routes, choose Next to skip route creation. You create routes later. Review the stage that API Gateway creates for you, and then choose Next. Choose Create.

Create routes

Now, we need to create a route. This route is the way to send incoming API requests to backend resources. So, these routes consist of two parts: an HTTP method and a resource path

For example, GET /items. For this example, API, we create four routes:

GET /items/{email}

GET /items

PUT /items

DELETE /items/{email}

  1. Go to API gateway and choose your API. Choose Routes Click Create.
  1. For Method, choose GET and enter /items/{id}. The {id} at the end of the path is a path parameter that API Gateway retrieves from the request path when a client makes a request. Choose Create.
  1. Repeat steps 1-2 for GET /items, DELETE /items/{id}, and PUT /items.

As we have created all the routes, now we will create an integration to connect a route to backend resources which is the Lambda function

For this example API, you create one Lambda integration that you use for all routes. 

  1. Go to the API Gateway dashboard and select your API. Click on Integrations and click  Manage integrations and then choose Create.
  1. In this step, let’s skip Attach this integration to a route. You complete that in a later step. For Integration type, choose Lambda function. For Lambda function, enter store-contact-details. Choose Create.

Attach your integration to routes

Now, we will integrate all API route with the same Lambda function. Once you attach the integration to all of the API’s routes, your Lambda function is invoked when a client calls any of your routes.

  1. Go to the API Gateway dashboard. Make sure to select the API you created earlier. Click  Integrations and choose a route. Click on “Create and attach an integration”
  1. Choose Attach integration.
  1. Repeat steps 4-6 for all routes.

Connecting it all Together

To get the URL to invoke your API, go to API Gateway dashboard and choose your API.

Note down your API’s invoke URL. It appears under the Invoke URL on the Details page.

Test

  1. Copy your API’s invoke URL.

The full URL looks like https://psnekb2lu1.execute-api.ap-south-1.amazonaws.com

  1. To create or update an item

Use the following command to create or update an item. The command includes a request body with the item’s ID, price, and name.

curl -v -X “PUT” -H “Content-Type: application/json” -d “{\”email\”: \”naresh@gmail.com\”, \”message\”: \”Hello from Finland\”, \”name\”: \”Naresh\”}” https://psnekb2lu1.execute-api.ap-south-1.amazonaws.com/items

  1. To get all items

Use the following command to list all items.

curl -v https://psnekb2lu1.execute-api.ap-south-1.amazonaws.com/items

  1. To get an item

Use the following command to get an item by its ID.

curl -v https://psnekb2lu1.execute-api.ap-south-1.amazonaws.com/items/pravin@gmail.com

  1. To delete an item

Use the following command to delete an item.

curl -v -X “DELETE” https://psnekb2lu1.execute-api.ap-south-1.amazonaws.com/items/pravin@gmail.com

Get all items to verify that the item was deleted.

curl -v https://psnekb2lu1.execute-api.ap-south-1.amazonaws.com/items

Conclusion

We used Amazon DynamoDB, API Gateway and AWS Lambda to collect details from users and save in the database.

Stay tuned for more such AWS hands-on step-by-step technical blogs!

Check out a blog post on How to add Dynamic Contact Forms for S3 Static Websites Using AWS Lambda, API Gateway & Amazon SES – A step-by-step guide!

1 thought on “How To Add AWS Dynamodb Database To A Static Website Hosted In Amazon S3? – A Step-by-step Guide!”

  1. Pingback: Let’s Connect AWS EC2 Instance using Session Manager – A step by step guide. - Pravin Mishra - AWS Mentor & Trainer

Leave a Comment

Your email address will not be published. Required fields are marked *