Aymen El Amri

Founder CEO at eralabs

Creating a Serverless Python API Using AWS Lambda & Chalice

Chalice is a python serverless microframework for AWS, created by Amazon Web Services.

It allows developers create and deploy applications that use Amazon API Gateway and AWS Lambda.

This is an introduction (probably more) for those who’d like to test and learn how to use this framework and host an API (or any other application) in AWS Lambda.

As part of my work in creating the content of Practical AWS training, this article is a prototype. The complete lesson will be included in the training with better examples and explanations.

If you are interested in Practical AWS training, you can make a preorder from now and get the training at almost its half-price.
If you are interested in our future trainings, you can register here and you’ll be added to our community in order to receive future updates.

When using AWS cloud, there are some considerations a user should take like IAM management. Chalice provides automatic IAM policy generation, which makes faster deploying an application.

Why Chalice ?

First of all because it is created by AWS.

It allows also the development and the deployment of Python serverless applications. Other frameworks will only help you develop serverless Javascript applications.

Finally, because I found it stable, easy and intuitive.

Requirements

To follow this tutorial, make sure you are using python2.7 or python3.6.

For Ubuntu 14 and 16, use:

sudo add-apt-repository ppa:jonathonf/python-3.6
sudo apt-get update
sudo apt-get install python3.6

Other OSs installation instructions, could be found here.

Before starting, you should have an AWS account and you should have configured your credentials in:

~/.aws/credentials

If you haven’t execute AWS configuration command, you’ll not find anything in your .aws folder. Use:

aws configure

Now create a virtual environment if you don’t like to touch your system libraries. Then activate it.

virtualenv -p python3.6 chalice_example
cd chalice_example
. bin/activate

Now install Chalice.

pip install chalice

Creating a Chalice Project

Now create a Chalice project:

chalice new-project chalice_project
cd chalice_project

You’ll find 2 files inside the project file:

.
├── app.py
└── requirements.txt

This is the default app.py program:

from chalice import Chalice
app = Chalice(app_name='chalice_project')
@app.route('/')
def index():
    return {'hello': 'world'}
# The view function above will return {"hello": "world"}
# whenever you make an HTTP GET request to '/'.
#
# Here are a few more examples:
#
# @app.route('/hello/{name}')
# def hello_name(name):
#    # '/hello/james' -> {"hello": "james"}
#    return {'hello': name}
#
# @app.route('/users', methods=['POST'])
# def create_user():
#     # This is the JSON body the user sent in their POST request.
#     user_as_json = app.current_request.json_body
#     # We'll echo the json body back to the user in a 'user' key.
#     return {'user': user_as_json}
#
# See the README documentation for more examples.
#

Creating our Function

In our example, we will create a function that will give you the md5sum of any string.

e.g:

import hashlib
m = hashlib.md5()
m.update("testing")
print m.hexdigest()

We need to install hashlib using PIP.

pip install hashlib

Open app.py, add the libraries we want to import:

from chalice import Chalice
import hashlib

Create an application

app = Chalice(app_name='chalice_project')

Add the default / route function:

@app.route('/')
def index():
    return {'response': 'ok'}

Now create the main function we are going to use:

@app.route('/md5/{string_to_hash}')
def hash_it(string_to_hash):
    m = hashlib.md5()
    m.update(string_to_hash.encode("utf-8"))
    return {'response': m.hexdigest()}

Notice that the route we are going to use is /md5/{string_to_hash}

We are using “{}” because string_to_hash is a variable.

Deploying

Now when you execute the deployement command

chalice deploy

, these instructions will be executed:

Creating role: chalice_project-dev
Creating deployment package.
Creating lambda function: chalice_project-dev
Initiating first time deployment.
Deploying to API Gateway stage: api
https://a23wxp5cve.execute-api.eu-west-1.amazonaws.com/api/

When you visit the provided url, you’ll get the configured message for the / route:

Let’s test this url to create the md5sum of the string “PracticalAWS”:

https://a23wxp5cve.execute-api.eu-west-1.amazonaws.com/api/md5/PracticalAWS

You should see something similar to the previous screenshot.

If you made an error in your code and don’t want to deploy each time you’d like to test, activate the debug of Chalice. This is how our code looks like:

from chalice import Chalice
import hashlib
app = Chalice(app_name='chalice_project')
app.debug = True
@app.route('/')
def index():
    return {'response': 'ok'}
@app.route('/md5/{string_to_hash}')
def hash_it(string_to_hash):
    m = hashlib.md5()
    m.update(string_to_hash.encode("UTF-8"))
    return {'response': str(m.hexdigest())}

Have you noticed that the last deployment was for the development environment ? If yes, nice you are focusing that those who are saying no :-)

chalice deploy --stage prod
Creating role: chalice_project-prod
Creating deployment package.
Creating lambda function: chalice_project-prod
Initiating first time deployment.
Deploying to API Gateway stage: api
https://27rezyfu06.execute-api.eu-west-1.amazonaws.com/api/

Now we have two APIs, one for dev and the other for prod. Execute these commands to show both urls:

chalice url --stage dev
chalice url --stage prod

Now, we have a new API Gateway rest API, Lambda function, and IAM.

Configurations

You can view our environments configurations by typing:

cat .chalice/deployed.json

e.g:

{
  "dev": {
    "api_handler_name": "chalice_project-dev",
    "api_handler_arn": "arn:aws:lambda:eu-west-1:998335703874:function:chalice_project-dev",
    "lambda_functions": {},
    "backend": "api",
    "chalice_version": "1.0.2",
    "rest_api_id": "rcnce4er7c",
    "api_gateway_stage": "api",
    "region": "eu-west-1"
  },
  "prod": {
    "api_handler_name": "chalice_project-prod",
    "api_handler_arn": "arn:aws:lambda:eu-west-1:998335703874:function:chalice_project-prod",
    "lambda_functions": {},
    "backend": "api",
    "chalice_version": "1.0.2",
    "rest_api_id": "4wf2ohyot4",
    "api_gateway_stage": "api",
    "region": "eu-west-1"
  }
}

Using your Own Domain

In order to use your own domain name,

  • Go to Route53, create a public zone for your domain, point your domain DNS to the created Route53 DNS records
  • Go to ACM, and create a certificate for your domain
  • Go to API Gateway settings, choose Custom Domain Names, choose your domain or subdomain and import the created certificate

To finish the last step, you can to wait for the cloudfront distribution for up to 40 minutes .. be patient :-)

Deleting Resources

You can delete an environment resources, for instance, for development, type :

chalice delete --stage dev

Join Us !

We are working hard in order to give you the best of what we master. We are building online courses for everyone and every level: Newbies, intermediate and skilled people.

Our goal is giving people the opportunity to enter the DevOps world trough quality courses and practical learning paths.

If you are interested in Practical AWS training, you can make a preorder from now and get the training at almost its half-price.
If you are interested in other future trainings, you can register here and you’ll be added to our community so that you can receive future updates.

More by Aymen El Amri

More Related Stories