Saiful Azad
5 min readMar 11, 2020

How to make a web site by using serverless technology and AWS services.

The architecture of the serverless website.

Project Link Click Here.

This is a serverless technology web service. Here we use Route 53, API Gateway, S3 Bucket, and DynamoDB. DynamoDB is a no SQL database management system. It is better than any other SQL database.

Module 1. Static Web Hosting

In this first, we have configured Amazon Simple Storage Service (S3) to host our web application’s stable resources. In the next modules, we will add dynamic functionality to these pages using JavaScript to call remote RESTful APIs built with AWS Lambda and Amazon API Gateway.

step 1. Select a Region.

step 2. Create an S3 Bucket.

step 3. Upload Content.

step 4. Add a Bucket Policy to Allow Public Reads.

step 5. Enable Website Hosting.

step 6. Validate your implementation.

Module 2: Serverless Service Backend

In this module, we’ll use AWS Lambda and Amazon DynamoDB to build a backend process for handling requests for our web applications. The browser application deployed in the first module allows users to request that a unicorn be sent to a location of their choice. In order to fulfill those requests, the JavaScript running in the browser will need to invoke a service running in the cloud.

step 1. Create an Amazon DynamoDB table.

step 2. Create an IAM Role for Your Lambda function.

step 3. Create a Lambda Function for Handling Requests.

POST text data function in Lambda. This function posts data to the database. This function stores all the text data type into the database. Such as a user’s email, name, address, phone number, comment, etc.

Below is a discussion of the function we use.

import boto3
import json
def lambda_handler(event, context):
dynamodb = boto3.resource('dynamodb')
table = dynamodb.Table('TABLE_NAME') #Table name.
table.put_item(
Item=json.loads(event['body']) #convert string to json.
)
return {
"statusCode": 200,
'headers': {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "*"
},
"body": (event['body'])
}

step 4. Generating a Presigned URL to Upload a File.

A user who does not have AWS credentials to upload a file can use a signed URL to perform the upload. The upload operation makes an HTTP POST request and requires additional parameters to be sent as part of the request.

Below is a discussion of the function we use.

import json
import logging
import boto3
from botocore.exceptions import ClientError
from botocore.client import Configdef create_presigned_post(bucket_name, object_name,
fields=None, conditions=None, expiration=3600):
"""Generate a presigned URL S3 POST request to upload a file
,
:param bucket_name: string
:param object_name: string
:param fields: Dictionary of prefilled form fields
:param conditions: List of conditions to include in the policy
:param expiration: Time in seconds for the presigned URL to remain valid
:return: Dictionary with the following keys:
url: URL to post to
fields: Dictionary of form fields and values to submit with the POST
:return: None if error.
"""

# Generate a presigned S3 POST URL
s3_client = boto3.client('s3', region_name='ap-southeast-1', config=Config(signature_version='s3v4'))
try:
response = s3_client.generate_presigned_post(bucket_name,
object_name,

# Conditions=[
# ["eq", "$success_action_redirect", "www.google.com"],
# {"success_action_status": "200"}],
ExpiresIn=expiration)
except ClientError as e:
logging.error(e)
return None
# The response contains the presigned URL and required fields
return response
def lambda_handler(event, context):
import uuid
name = str(uuid.uuid4())
ext = event["queryStringParameters"]['extension']
key = f'{name}.{ext}'
response = create_presigned_post('BUCKET_NAME', key)
# TODO implement
return {
'headers': {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "*"
},
'statusCode': 200,
'body': json.dumps(response)
}

The generated signed URL includes both a URL and additional fields that must be passed as part of the subsequent HTTP POST request.

The following code demonstrates how to use the requests package with a signed POST URL to perform a POST request to upload a file to S3.

step 5. Create a Lambda Function for the GET request.

import boto3
import json
def lambda_handler(event, context):
dynamodb = boto3.resource('dynamodb')
table = dynamodb.Table('TABLE_NAME') #DynamoDB Tabale name.
x= table.scan() #scan DynamoDB table and get all data.
# TODO implement
dump_data = json.dumps(x['Items'])
return {
"statusCode": 200,
'headers': {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "*"
},
"body": dump_data
}

We have used it here to view a client’s comments and reviews of our website. This is where all the data is gated by running a query function on our table.

step 6. Create a Lambda Function for the GET request.

import boto3
import json
def lambda_handler(event, context):
# TODO implement
dynamodb = boto3.resource('dynamodb')
table = dynamodb.Table('TABLE_NAME') #DynamoDB table name.
params = event['pathParameters']
item = table.delete_item(
Key = params
)

message = {
'sucess': True,
'message': 'Deleted'
}
return {
"statusCode": 200,
'headers': {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "*"
},

"body": json.dumps(message)
}

This function is used when deleting data from a database. You can also delete the item using dynamodb.table.delete_item():

Module 3. AWS SES

Amazon Simple Email Service (SES) is an email platform that provides an easy, cost-effective way for you to send and receive email using your own email addresses and domains.

import boto3
import json
class Email(object):
def __init__(self, to, subject):
self.to = to
self.subject = subject
self._html = None
self._text = None
self._format = 'html'
def html(self, html):
self._html = html
def text(self, text):
self._text = text
def send(self, from_addr=None):
body = self._html

def order_update(id, email, status):
user = OrderNotification(id, email)
user.status = status
user.save()
self.to = [self.to]
if not from_addr:
from_addr = 'Your_Mail_Address'
if not self._html and not self._text:
raise Exception('You must provide a text or html body.')
if not self._html:
self._format = 'text'
body = self._text
connection = boto3.client( 'ses', region_name='us-east-1')return connection.send_email(
Source=from_addr,
Destination={
'ToAddresses': self.to
},
Message={
'Subject': {
'Data': self.subject,
'Charset': 'UTF-8'
},
'Body': {
'Text': {
'Data': self._text,
'Charset': 'UTF-8'

}
}
})

def lambda_handler(event, context):
# TODO implement
record_list = event['Records']

print(event)

Module 4. RESTful APIs

In this module, we used the Amazon API Gateway to express the Lambda function built into the previous module as a Restool API. This API will be accessible to the public Internet.

step 1. Create a New REST API.

step 2. Create a new resource and method.

step 3. Deploy Your API.

step 4. Update the Website Config.

step 5. Validate your implementation.