chalice-http-toolkit

chalice-http-toolkit enables a Flask like website building experience using Chalice, AWS Lambda, API Gateway & CloudFront. It does this by bolting on Jinja2 templates, and CloudFront cache management layer.

Installation

Base installation via pip:

pip install chalice-http-toolkit

The above command only installs the base dependancies, there is also an additional extra_requires directive shown below that installs packages which would normally push your Lambda package over the 250MB limit.

For local testing the rest of the dependancies can be installed via:

pip install chalice-http-toolkit[layered]

For deployments to AWS Lambda the following layers should be used:

arn:aws:lambda:us-east-2:770693421928:layer:Klayers-python38-jinja2:2
arn:aws:lambda:us-east-2:770693421928:layer:Klayers-python38-Pillow:10

Chalice config.json

A basic Chalice config.json is defined below which has two stages, dev is meant for local testing and prod is the stage which gets deployed to AWS Lambda. The STAGE environment variable must be defined for local testing to work around some differences between AWS API Gateway behaviour vs the way locally served API works.

{
  "version": "2.0",
  "app_name": "example",
  "stages": {
    "dev": {
      "api_gateway_stage": "dev",
      "lambda_timeout": 60,
      "lambda_memory_size": 64,
      "environment_variables": {
        "STAGE": "dev"
      },
    },
    "prod": {
      "api_gateway_stage": "prod",
      "layers": ["arn:aws:lambda:us-east-2:770693421928:layer:Klayers-python38-jinja2:2",
                 "arn:aws:lambda:us-east-2:770693421928:layer:Klayers-python38-Pillow:10"],
      "lambda_timeout": 60,
      "lambda_memory_size": 64,
      "environment_variables": {
        "STAGE": "prod"
      }
    }
  }
}

Project Structure

Templates and static content needs to be placed in the chalicelib directory because that is where additional content is packaged into the deployment by Chalice.

Architecture

Placing CloudFront in front of a chalice-http-toolkit website is not required, but if your website is popular it probably starts to make sense given that every invocation ends up costing more then it would for CloudFront to server the website.

ContentManager

class chalice_http_toolkit.content.ContentManager[source]

This class is designed to support:

  • serving static content (such as Javascript/CSS). Although these might be better served by S3 depending on scale.

  • rendering Jinja2 templates

  • support generating 304 redirects

  • support returning JSON Responses

  • serving assets

  • converting images based on the accepts header in a request

  • cleaner handling of binary content

Every chalice-http-toolkit app requires a ContentManager be created, usually right after the Chalice app is created.

CloudFront

class chalice_http_toolkit.cloudfront.CloudFront[source]

This class is designed to support:

  • caching static content by modifed dates

  • caching Jinja2 templates by hashing dependancies (ie arguments and child templates) without rendering.

  • caching assets

Using this module is optional, but it is best practice.

Gotchas

There are a few differences between locally testing & a deployed instance of a Chalice website. They are detailed below.

Binary Content

Due to the way API Gateway handles binary content, the binary content is Base64 encoded in the absence of an Accepts header in the request. This restriction does not apply for local testing.

Request & Reponse Limits

API Gateway has a request & response filesize limit of 10MB. This restriction does not apply for local testing.

Cold Starts

Chalice based websites are vulnerable to the Lambda Coldstart problem. A cold start happens when you execute an inactive function. The delay comes from AWS provisioning your selected runtime container and then running your function. Functions stay ‘warm’ for approximately 5 minutes, which means they respond to requests much quicker. After this period of time, the contianer is dropped by AWS and a cold start needs to happen.