Package: cloud-events
cloud-events-handlerSend CloudEvents (and others) to an ASGI or WSGI applicationcloud-events-handlerconverts CloudEvents and other vendor specific events into ASGI/WSGI calls for your applicationsProblemHow does an ASGI/WSGI application handle events from the cloud provider of choice?Events could beCloudEventsAWS EventsGoogle, Azure events tooExamples: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 eventWhy 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.Installpip install cloud-eventsUsageExample Django ApplicationAWS S3 ExampleIncludecloud-eventsin the requirementsSet the handler of a lambda tocloud_events.handler.handlerSetWSGI_APPLICATIONto the python path of the WSGI applicationProcess the S3 event at/aws.s3of your applicationExamplemy-django-app
  views
    BooksGET /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 bookIn this example instead of reacting only to an API Gateway or ALB event, we can process any event in our WSGI application.SettingsTwo settings are used to configure the cloud-event handler.RequiredWSGI_APPLICATIONpoints to the python path of the WSGI applicationASGI_APPLICATIONpoints to the python path of the ASGI applicationOptionalWSGI_ENVIRONpoints to the python path of a module and is expected to end at a dictionary.ExampleWSGI_ENVIRON# in app/config
environ = {
    "HTTP_ACCEPT": "application/vnd.api+json",
    "PATH_INFO": "/books/",
    "REQUEST_METHOD": "get"
}

WSGI_ENVIRON = app.config.environThis 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 HandlerYou can use a custom handler instead of the provided handler by importing the handler function and passing theeventandcontext.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 MappingEventPath AttributeDynamic WSGI PathCloudEvent$.source/myContextAWS EventBridge$.source/com.my.eventAWS CloudWatch Event$.source/com.my.eventAWS IOT Event$.event.eventName/myChargedEventEvents 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 EventPattern AttributesStatic WSGI PathS3$.Records[0].eventSourcewith:replaced by./aws.s3CodeCommit$.Records[0].eventSource/aws.codecommitDynamoDB$.Records[0].eventSource/aws.dynamodbEC2 Lifecycle$.source/aws.ec2Kinesis$.Records[0].eventSourcewith:replaced by./aws.kinesisSNS$.Records[0].eventSourcewith:replaced by./aws.snsSQS$.Records[0].eventSourcewith:replaced by./aws.sqsSES$.Records[0].eventSourcewith:replaced by./aws.sesLex$.botand$.outputDialogModeand$.currentIntent/aws.lexKinesis Firehose$.records[0].kinesisRecordMetadata/aws.kinesis.firehoseCognito$.identityIdand$.identityPoolId/aws.cognitoConfig$.configRuleId/aws.configCloudFront$.Records[0].cf/aws.cloudfrontCloudFormation$.LogicalResourceId/aws.cloudformationAlexa$.headerand$.payload/aws.alexaEvents 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 areessentiallystatic since the route is defined by the message but that data is from AWS and unlikely to change.Getting StartedClone this repoInstall toxpip install toxRun teststoxAll package code is insrcFrequently Asked QuestionsDoes this have ASGI support?YesAre 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 themangumuses. If the app is ASGI that is a well suited library for API gateway eventsFor AWS ALB and API Gateway eventsserverless-wsgi,zappa, orawsgiare good optionsAre the URLs I add to handle the events also callable?The urls used for eventscouldalso be called via HTTP if they are exposed on an API GatewayDoes this encourage monolithic lambdas?MaybeHistoryThis 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   |          |
         |          +---------------------+          |
         |                                           |
         +-------------------------------------------+