Building Modern Serverless API's with AWS: DynamoDB, Lambda, and API Gateway(Part 5)
Building a serverless API with SAM.
I love creating and writing about the creation of software.
Search for a command to run...
Building a serverless API with SAM.
I love creating and writing about the creation of software.
No comments yet. Be the first to comment.
A Technical / Non Technical overview of the dynamoDb for Beginners
An oversimplification of what dynamoDB is, and how it can be used for app development.
Watch the complete Video on Youtube https://www.youtube.com/watch?v=kKX-8L_R2XM Prerequisites Before proceeding make sure you have these dependencies Docker Python 3.11 and above AWS CLI Full access to a foundation model. For this workshop, we'll...

Introduction In a previous workshop, Building event-driven applications with AWS sam and python we built an e-commerce ordering service using AWS SAM, API Gateway, Lambda and Python. Here's the solutions architecture. In that workshop, whenever a ne...

Github Repository https://github.com/EducloudHQ/introduction_to_gen_ai Skill up with serverless on Educloud https://www.educloud.academy/content/da99ad07-7efa-41e7-ba50-b18e6b89e10d This post is an introductory lesson to building AI-enhanced serverle...

Introduction Serverless computing is a cloud-based approach to application development that eliminates the need for provisioning and managing servers. Instead, developers focus on writing code that is triggered by events such as HTTP requests or data...

https://github.com/trey-rosius/sam_stepfunctions Hey!!! How you doing? In this post, we’ll look at how to build a workflow, using SAM as IaC, Appsync, and python. Prerequisites Install AWS Cli (https://docs.aws.amazon.com/cli/latest/userguide/cli-c...

Welcome to the last part in "Building Modern Serverless API's with AWS" series. Here's a recap of what we've done so far.
In Part 1 of this series, we modeled and designed access patterns for our application entities.
In Part 2, we designed the primary key and Global Secondary Index, created a sample database schema using NoSql Workbench, and saw clearly each access pattern for our app.
In Part 3, we started coding up our API. We created a project using SAM and wrote a couple of scripts to Create a user, Get a user by ID and also create a post
In Part 4, we created scripts to update posts, fetch all posts by a given user, thereby returning a multi Entity response. We built and deployed our API with SAM. And tested some of the API endpoints using PostMan.
In this post, we would write and tests scripts for
import json
import logging
import os
import time
import uuid
import boto3
dynamodb = boto3.resource('dynamodb')
def create_comment(event, context):
data = json.loads(event['body'])
if 'commentText' not in data:
logging.error("Validation Failed")
raise Exception("Couldn't create a comment")
timestamp = str(time.time())
table = dynamodb.Table(os.environ['TABLE_NAME'])
item = {
'PK': "POST#{}#{}".format(data['postId'],data['timestamp']),
'SK': "COMMENT#{}#{}".format(str(uuid.uuid1()),timestamp),
'commentId': str(uuid.uuid1()),
'postId': data['postId'],
'userId': data['userId'],
'commentText': data['commentText'],
'status': data['status'],
'createdOn': timestamp
}
# write the post to the database
table.put_item(Item=item)
# create a response
response = {
"statusCode": 200,
"body": json.dumps(item)
}
return response
Nothing new to talk about. It's the same as Create User or Create Post. Maybe take note of the PK and SK values.
Here's how you configure the CreateCommentFunction in the SAM template.yaml file.
CreateCommentFunction:
Type: AWS::Serverless::Function # More info about Function Resource: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction
Properties:
CodeUri: comments/
Handler: create.create_comment
Runtime: python3.8
Policies:
- DynamoDBCrudPolicy:
TableName: data
Events:
HttpPost:
Type: Api # More info about API Event Source: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#api
Properties:
Path: /comment
Method: post
import os
import json
import boto3
import decimalencoder
from botocore.exceptions import ClientError
from boto3.dynamodb.conditions import Key
dynamodb = boto3.resource('dynamodb')
def get_post_comments(event, context):
# print(event)
# print(event['pathParameters'])
print("print this ")
table = dynamodb.Table(os.environ['TABLE_NAME'])
postId = 'POST#{}#{}'.format(event['pathParameters']['id'],event['pathParameters']['timestamp'])
print(postId)
result = table.query(
KeyConditionExpression=
Key('PK').eq(postId),
ScanIndexForward=True
)
# create a response
response = {
"statusCode": 200,
"body": json.dumps(result["Items"],
cls=decimalencoder.DecimalEncoder)
}
print(response)
print("Query successful.")
return response
At the very top of the script, we import boto3 and a couple of utility classes that we'll be needed in our script. Next, we get the post id sent through the API endpoint. We query our table while assigning a key condition expression that gets all comments for any post whose ID is equal to the postId + timestamp sent through the API endpoint.
Then we configure the function in the SAM template.yaml like so
GetPostCommentsFunction:
Type: AWS::Serverless::Function # More info about Function Resource: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction
Properties:
CodeUri: posts/
Handler: get_comments_post.get_post_comments
Runtime: python3.8
Policies:
- DynamoDBCrudPolicy:
TableName: data
Events:
HttpPost:
Type: Api # More info about API Event Source: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#api
Properties:
Path: /posts/{id}/{timestamp}/comments
Method: get
GlobalSecondaryIndexes:
- IndexName: "GSI1"
KeySchema:
- AttributeName: "status"
KeyType: "HASH"
Projection:
ProjectionType: "ALL"
ProvisionedThroughput:
ReadCapacityUnits: "1"
WriteCapacityUnits: "1"
The Global Secondary Index name is "GSI1". The status is a HASH Key.
With that in place, let's look at the script.
Create a file called fetch_posts_by_status.py inside the posts folder and add type in the following code.
import os
import json
import boto3
import decimalencoder
from botocore.exceptions import ClientError
from boto3.dynamodb.conditions import Key
dynamodb = boto3.resource('dynamodb')
def fetch_post(event, context):
# print(event)
# print(event['pathParameters'])
print("print this ")
table = dynamodb.Table(os.environ['TABLE_NAME'])
result = table.query(
IndexName="GSI1",
KeyConditionExpression=
Key('status').eq(event['pathParameters']['status']),
ScanIndexForward=True
)
# create a response
response = {
"statusCode": 200,
"body": json.dumps(result["Items"],
cls=decimalencoder.DecimalEncoder)
}
print(response)
print("Query successful.")
return response
Take note of the query IndexName. That's the index name we set when we created the GSI above.
Lets now declare this function in the SAM template.yaml file.
FetchPostsByStatusFunction:
Type: AWS::Serverless::Function # More info about Function Resource: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction
Properties:
CodeUri: posts/
Handler: fetch_posts_by_status.fetch_post
Runtime: python3.8
Policies:
- DynamoDBCrudPolicy:
TableName: data
Events:
HttpPost:
Type: Api # More info about API Event Source: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#api
Properties:
Path: /posts/status/{status}
Method: get
And that's all. Be sure to grab the complete code from Github. https://github.com/trey-rosius/modern_serverless_api
You can go-ahead to build and deploy the API.
sam build --use-container
sam deploy --guided
As always, I do my testing with Postman.


I had lots of fun creating this series and I do hope you felt the same, reading and practicing along.
I'm still working on my blogging/teaching skills, so if I didn't explain some concepts in a cool and detailed manner, please bear with me I'll get better with time.
If you loved this series, please leave feedback or like. Also, do leave feedback, in case you find mistakes. I'll be happy to correct them.
In the next article, we'll consume this API in a mobile and web application. So stay tuned. Till next time, my brothers and sisters ✌🏿