Skip to main content

Send CloudEvents (and AWS Events) to an ASGI or WSGI application

Project description

cloud-events-handler

Send CloudEvents (and others) to an ASGI or WSGI application

cloud-events-handler converts CloudEvents and other vendor specific events into ASGI/WSGI calls for your applications

Problem

How does an ASGI/WSGI application handle events from the cloud provider of choice?

Events could be

Examples:

CloudEvent -> Lambda that processes the data in the event
S3 event -> Lambda that processes the file added
EventBridge -> Lambda that processes the data in the event

Why would you want to do this?

A whole application has parts that are accessible via HTTP and some that are reactive to non-HTTP events. The latter kind of event may need to be handled or processed with components from your application, e.g. middleware, models, serializers, etc.

Install

pip install cloud-events

Usage

Example Django Application

AWS S3 Example

  1. Include cloud-events in the requirements
  2. Set the handler of a lambda to cloud_events.handler.handler
  3. Set WSGI_APPLICATION to the python path of the WSGI application
  4. Process the S3 event at /aws.s3 of your application

Example

my-django-app
  views
    Books
GET /books  - returns a list of books

POST /books - possible but what if the book is > 6 MB? Lambda cannot handle that.
So let us allow users to upload that book directly to S3.
Now how do we get the metadata in the database when the user uploads the book?
We configure an event for each S3 object creation in our bucket.
Therefore, when the S3 event is sent, we want our Lambda to have access to the same code that the rest of our application uses.

DELETE /books/{id} - deletes a book

In this example instead of reacting only to an API Gateway or ALB event, we can process any event in our WSGI application.

Settings

Two settings are used to configure the cloud-event handler.

Required

  • WSGI_APPLICATION points to the python path of the WSGI application
  • ASGI_APPLICATION points to the python path of the ASGI application

Optional WSGI_ENVIRON points to the python path of a module and is expected to end at a dictionary.

Example WSGI_ENVIRON

# in app/config
environ = {
    "HTTP_ACCEPT": "application/vnd.api+json",
    "PATH_INFO": "/books/",
    "REQUEST_METHOD": "get"
}

WSGI_ENVIRON = app.config.environ

This is merged with the default environ and passed to the WSGI application.

Default environ:

{
    "CONTENT_TYPE": "application/json",
    "REQUEST_METHOD": "post",
    "PATH_INFO": "/",
    "SCRIPT_NAME": "",
    "SERVER_NAME": "localhost",
    "SERVER_PORT": "80",
    "SERVER_PROTOCOL": str("HTTP/1.1"),
    "wsgi.input": None,
    "wsgi.version": (1, 0),
    "wsgi.run_once": False,
    "wsgi.multiprocess": False,
    "wsgi.multithread": False,
    "wsgi.url_scheme": "http",
}

Custom Handler

You can use a custom handler instead of the provided handler by importing the handler function and passing the event and context .

from cloud_events.handler import handler

def my_handler(event, context):
    do_my_special_thing()
    return handler(event, context)

The default handler returns a dictionary.

{
    "status_code": status_code <str>,
    "body": body <str>,
    "headers": headers <dict>,
}

Event Path Mapping

Event Path Attribute Dynamic WSGI Path
CloudEvent $.source /myContext
AWS EventBridge $.source /com.my.event
AWS CloudWatch Event $.source /com.my.event
AWS IOT Event $.event.eventName /myChargedEvent

Events with a dynamic WSGI path mean that the path called in the WSGI application is dependent on the data in the event message at the path attribute specified.

AWS Event Pattern Attributes Static WSGI Path
S3 $.Records[0].eventSource with : replaced by . /aws.s3
CodeCommit $.Records[0].eventSource /aws.codecommit
DynamoDB $.Records[0].eventSource /aws.dynamodb
EC2 Lifecycle $.source /aws.ec2
Kinesis $.Records[0].eventSource with : replaced by . /aws.kinesis
SNS $.Records[0].eventSource with : replaced by . /aws.sns
SQS $.Records[0].eventSource with : replaced by . /aws.sqs
SES $.Records[0].eventSource with : replaced by . /aws.ses
Lex $.bot and $.outputDialogMode and $.currentIntent /aws.lex
Kinesis Firehose $.records[0].kinesisRecordMetadata /aws.kinesis.firehose
Cognito $.identityId and $.identityPoolId /aws.cognito
Config $.configRuleId /aws.config
CloudFront $.Records[0].cf /aws.cloudfront
CloudFormation $.LogicalResourceId /aws.cloudformation
Alexa $.header and $.payload /aws.alexa

Events with a static WSGI path mean that the path called in the WSGI application is the same for each event matching the pattern. Some events are essentially static since the route is defined by the message but that data is from AWS and unlikely to change.

Getting Started

  1. Clone this repo
  2. Install tox pip install tox
  3. Run tests tox

All package code is in src

Frequently Asked Questions

Does this have ASGI support?

Yes

Are the responses JSON serializable?

Yes. This is also to support SQS which needs a response from a lambda. The response code from the WSGI application is sent back in the default response i.e. a 500 in the WSGI app will then be sent to SQS if using the default handler.

Does this have API Gateway/ALB support?

No. For now use other libraries as those are more fully featured.

This uses the same class the mangum uses. If the app is ASGI that is a well suited library for API gateway events

For AWS ALB and API Gateway events serverless-wsgi, zappa, or awsgi are good options

Are the URLs I add to handle the events also callable?

The urls used for events could also be called via HTTP if they are exposed on an API Gateway

Does this encourage monolithic lambdas?

Maybe

History

This started out with the question, "Can we take an AWS event, in a generic way, and send it through to Django via a handler that makes full use of Django?"

Yes we can :)

Flow


                     +------------------+
                     |                  |
                     |  Event Producer  |
                     |                  |
                     +------------------+
                               |
                               |
         +---------------------v---------------------+
         |                                           |
         |              Event Consumer               |
         |                                           |
         |          +---------------------+          |
         |          |Handler              |          |
         |          |                     |          |
         |          |Any compute that     |          |
         |          |handles/processes the|          |
         |          |event                |          |
         |          +---------------------+          |
         |                     |                     |
         |                     v                     |
         |          +---------------------+          |
         |          |Adapter              |          |
         |          |                     |          |
         |          |Adapts events into   |          |
         |          |CloudEvents format   |          |
         |          +---------------------+          |
         |                     |                     |
         |                     v                     |
         |          +---------------------+          |
         |          |Interface            |          |
         |          |                     |          |
         |          |Interfaces for A/WSGI|          |
         |          +---------------------+          |
         |                     |                     |
         |                     v                     |
         |          +---------------------+          |
         |          |Application          |          |
         |          |                     |          |
         |          |A/WSGI application   |          |
         |          +---------------------+          |
         |                                           |
         +-------------------------------------------+

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distribution

cloud_events-0.3.0-py3-none-any.whl (7.1 kB view details)

Uploaded Python 3

File details

Details for the file cloud_events-0.3.0-py3-none-any.whl.

File metadata

  • Download URL: cloud_events-0.3.0-py3-none-any.whl
  • Upload date:
  • Size: 7.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/4.0.2 CPython/3.11.7

File hashes

Hashes for cloud_events-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 85fc7fc9635e315a5a443aba2a314ae02aedaed8b793402b5707c3ddb3094551
MD5 409353a20c8d91ce4a9f1b7c73fb2484
BLAKE2b-256 fbcfcec3026d42b17270c82e08798763e923d500f6ab4b5a4ee11191c3e7c320

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page