Build your RESTful API with AWS right NOW

Hello everyone, I am so happy to introduce you today the coolest way to create an endpoint!

Whatever you want to save files or data in a Database, this post will show you how to easily make a Restful API quickly and why not a full project. But first, let’s introduce you some important points to begin.

You need to setup your environment

You need to create an AWS account

Deploying a Lambda in AWS without an account is impossible. However, it’s free and easy like any website on the Internet. Just go to aws.amazon.com and create a new account. Don’t forget to secure your root user with 2FA! And protect it with a strong password.

You have to create a Programmable User

A programmable user is a user like that connects to AWS with your account. It represents your computer and maybe an application like a website or a mobile app. It’s based on limited access that you give to this user. So, be careful. Don’t add a full access to administrate your account.

In our case, it’s necessary to run CLI commands to our computer, that’s why you have to install AWS CLI.

You should install some dependencies

Now, your computer is able to connect to AWS via CLI. Then you need to install SAM (Serverless Application Model), This tool will provide a command line tool to initiate, build and deploy the RESTFul Api (Lambda). But, you need to install Docker to be able to run on local. Simply, Docker must be installed in all developers’s computer, right?

Generate a Lambda Function

The RESTFull API in AWS is a stack. SAM will create a template that creates all necessary resources to create the endpoint. Technically, the RESTFull Application is:

  • An API Gateway with secured URL
  • Lambda Function that will contain the logic (FastAPI Application)
  • S3/DynamoDB/SQS… All AWS resources that Applications needs
  • Roles, Policies that allow your Lambda for access to different resources

This stack is presented by only one file named template.yaml. It’s a Yaml file that list all these resources adding configurations.

Our first template

In our example, we will create an endpoint that saves posted data in DynamoDB (Database), This RESTFul API will be named MyStoreAPI. So, let’s bootstrap a lambda template with the command bellow.

sam init

Sam init is the command that initiates a lambda project with a very helpful questions like this.

Which template source would you like to use?
        1 - AWS Quick Start Templates
        2 - Custom Template Location
Choice: 1

Let’s chose the first option to have a quick starter template.

There is two ways to deploy a lambda function, by pushing a zip file containing all packages and codes in it and publishing a Docker image in the official repository Amazon ECR. In this case, we will chose the zip package.

What package type would you like to use?
        1 - Zip (artifact is a zip uploaded to S3)
        2 - Image (artifact is an image uploaded to an ECR image repository)
Package type: 1

Then, we should select the runtime

Which runtime would you like to use?
        1 - nodejs14.x
        2 - python3.9
        3 - ruby2.7
        4 - go1.x
        5 - java11
        6 - dotnetcore3.1
        7 - nodejs12.x
        8 - nodejs10.x
        9 - python3.8
        10 - python3.7
        11 - python3.6
        12 - python2.7
        13 - ruby2.5
        14 - java8.al2
        15 - java8
        16 - dotnetcore2.1
Runtime: 2

This is a list of all Run-times we can chose. But, If you want a custom runtime you can make your custom Docker image. In our case we will select Python3.9.

After few seconds, SAM will download files, configure and create a full project for us:

We have to update the code

Before starting coding the endpoint there is some code updates to do. First, let’s rename hello_world to src/ because It’s the folder that contains the source code. Then , rename everything related to hello_world to src in template.yaml in CodeUri: hello_world/, the function name, and the README.md file. Also you need to update the API Gateway’s configuration by edition the same file to this code:

      Events:
        Root:
          Type: Api
          Properties:
            Path: /
            Method: ANY
        NonRoot:
          Type: Api
          Properties:
            Path: /{proxy+}
            Method: ANY

This method will accept all verbs (GET, POST, PUT, DELETE) to roots and other routes and will configure the API Gateway to accept all the requests.

Under the Function name in template.yaml we have to add these lines:

    Properties:
      Policies:
        - DynamoDBCrudPolicy:
            TableName: MyStoreDb # need to be created
        - S3CrudPolicy:
            BucketName: !Ref MyStoreS3Bucket
# To add a bucket releated to this project add this lines
#  MyStoreS3Bucket:
#    Type: AWS::S3::Bucket

These lines will add policies to have access to CRUD DynamoDB and an S3 Bucket.

✍️ Let’s start coding the main Endpoint

Great! Now we are ready to start coding the RESTFul endoint. So, let’s update requirements.txt to put FastAPI and other packages we need.

requests # to get a http client
boto3 # This package helps us to use AWS services
fastapi # The FastAPI official package
mangum # This will run FastAPI server as a function
pydantic # Data validation and settings management

Now we are ready to write a Python API and here some example to get started with FastAPI!

This is app.py file:

import os
from fastapi import FastAPI
from mangum import Mangum
from starlette.datastructures import CommaSeparatedStrings
import os
from routes import router


ALLOWED_HOSTS = CommaSeparatedStrings(os.getenv("ALLOWED_HOSTS", ""))
API_VERSION_PATH = "/api/v1"
PROJECT_NAME = "My Store API"


stage = os.environ.get('STAGE', None)
root_path = f"/{stage}" if stage else "/"

description = """
my Store API 🚀
"""

app = FastAPI(
    title=PROJECT_NAME,
    description=description,
    root_path=root_path,
    version="0.0.1"
)

app.include_router(router, prefix=API_VERSION_PATH )


handler = Mangum(app)

And this is routes.py file

from fastapi import APIRouter, HTTPException
from starlette.requests import Request
import json


router = APIRouter()

# This is an example but may be used as a health check
@router.get("/status", description="This is a health check", tags=["Health Check"])
def get_status():
    # Create a client.
    return {"status": "OK"}

As we can see in app.py file, handler = Mangum(app). This means that AWS Lambda needs to run handler function to invoke all the API. That’s why, in template.yaml we should specify this in this line Handler: app.handler (file_name.function_name)

We are ready to deploy the function and continue coding the Endpoint. For more code examples, go check my other posts about python and lambda like this post Files in S3 AWS Python Lambda, how to handle them?

☁️ Deploy the Lambda Function

To deploy the Lambda we only need to run sam deploy --guided and follow the guide.

Configuring SAM deploy
======================

        Looking for config file [samconfig.toml] :  Found
        Reading default arguments  :  Success

        Setting default arguments for 'sam deploy'
        =========================================
        Stack Name [sam-app]: 
        AWS Region [eu-west-3]: 
        #Shows you resources changes to be deployed and require a 'Y' to initiate deploy
        Confirm changes before deploy [Y/n]: Y
        #SAM needs permission to be able to create roles to connect to the resources in your template
        Allow SAM CLI IAM role creation [Y/n]: Y
        DocusignApiFunction may not have authorization defined, Is this okay? [y/N]: y
        DocusignApiFunction may not have authorization defined, Is this okay? [y/N]: y
        Save arguments to configuration file [Y/n]: Y
        SAM configuration file [samconfig.toml]: 
        SAM configuration environment [default]: 

This will create the samconfig.toml file that will be used later without –guided option, most importantly, SAM will deploy the CloudFormation stack by creating the API Gateway, the Lambda function, roles and policies and all resources from the template.yaml on this stack.

This stack can be delete with one command and can be updated by adding more resources so pay attention by having a meaningful name of the stack.

Update the API Gateway

After deploying the stack, the API Gateway will create two stages (Prod and Stage) that we need to update in the console by deleting them first, then, create a new one with a given name dev

Congraculation! you endpoint is live in this link https://{APIGW-ID}.execute-api.{REGION}.amazonaws.com/dev 👏

Helpful commands to manage your lambda

I create a Makefile that includes all commands I want to run. Then, I can only type make logs to show logs in real time or make remove to destroy and clean the stack. You have to clean the stack after developing because the API Gateway is public.

REGION= the AWS Region
STACK_NAME= the stack name 
LAMBDA= The Lambda Function name from template.yaml

build:
	sam build --use-container

logs:
	sam logs -n ${LAMBDA} --stack-name ${STACK_NAME} --tail

test:
	python -m pytest tests -v

local:
	sam build --use-container
	sam local start-api

remove:
	aws cloudformation delete-stack --stack-name ${STACK_NAME}

describe:
	aws cloudformation describe-stack-resources --stack-name ${STACK_NAME}

If you have any question or comment, please comment on this Post.

If you want to hash a file in a Lambda check this post https://kaliex.co/how-to-hash-a-file-in-a-bucket-s3-using-aws-lambda/

You Might Also Like
1 Comment

Leave a Reply