Skip to main content

AWS Lambda & API Gateway support for ASGI

Project description

Mangum

Package version Build Status PyPI - Python Version

Mangum is an adapter for using ASGI applications with AWS Lambda & API Gateway. It is intended to provide an easy-to-use, configurable wrapper for any ASGI application deployed in an AWS Lambda function to handle API Gateway requests and responses.

Documentation: https://mangum.io/

Features

  • API Gateway support for HTTP, REST, and WebSocket APIs.

  • Multiple storage backend interfaces for managing WebSocket connections.

  • Compatibility with ASGI application frameworks, such as Starlette, FastAPI, and Quart.

  • Support for binary media types and payload compression in API Gateway.

  • Works with existing deployment and configuration tools, including Serverless Framework and AWS SAM.

  • Startup and shutdown lifespan events.

Requirements

Python 3.6+

Installation

pip install mangum

Usage

The Mangum adapter class is designed to wrap any ASGI application and returns a callable. It can wrap an application and be assigned as the handler:

from mangum import Mangum

# Define an ASGI application

handler = Mangum(app)

However, this is just one convention, you may also intercept events and construct the adapter instance separately:

def handler(event, context):
    if event.get("some-key"):
        # Do something or return, etc.

    asgi_handler = Mangum(app)
    response = asgi_handler(event, context) # Call the instance with the event arguments

    return response

Configuration

The adapter accepts various arguments for configuring lifespan, logging, HTTP, WebSocket, and API Gateway behaviour.

handler = Mangum(
    app,
    enable_lifespan=True,
    log_level="info",
    api_gateway_base_path=None,
    text_mime_types=None,
    dsn=None,
    api_gateway_endpoint_url=None,
    api_gateway_region_name=None
)

Parameters

  • app : ASGI application

    An asynchronous callable that conforms to ASGI specification version 3.0. This will usually be a framework application instance that exposes a valid ASGI callable.

  • enable_lifespan : bool

    Specify whether or not to enable lifespan support. The adapter will automatically determine if lifespan is supported by the framework unless explicitly disabled.

  • log_level : str

    Level parameter for the logger.

  • api_gateway_base_path : str

    Base path to strip from URL when using a custom domain name.

  • text_mime_types : list

    The list of MIME types (in addition to the defaults) that should not return binary responses in API Gateway.

  • dsn: str

    Connection string to configure a supported WebSocket backend.

  • api_gateway_endpoint_url : str

    The endpoint url to use when sending data to WebSocket connections in API Gateway. This is useful if you are debugging locally with a package such as serverless-offline.

    Defaults to the AWS_REGION value in the AWS Lambda environment.

  • api_gateway_region_name : str

    The region name of the API Gateway contains the connections created by WebSocket APIs.

    Defaults to the AWS_REGION value in the AWS Lambda environment.

Event and context

The AWS Lambda handler has event and context parameters. These are available in the ASGI scope object:

scope['aws.event']
scope['aws.context']

Examples

The examples below are ASGI applications (non-framework) with minimal configurations. You should be able to replace the app in these example with most ASGI framework application instances. Please read the HTTP and WebSocket docs for more detailed configuration information.

HTTP

from mangum import Mangum

async def app(scope, receive, send):
    await send(
        {
            "type": "http.response.start",
            "status": 200,
            "headers": [[b"content-type", b"text/plain; charset=utf-8"]],
        }
    )
    await send({"type": "http.response.body", "body": b"Hello, world!"})


handler = Mangum(app)

WebSocket

from mangum import Mangum

html = b"""
<!DOCTYPE html>
<html>
    <head>
        <title>Chat</title>
    </head>
    <body>
        <h1>WebSocket Chat</h1>
        <form action="" onsubmit="sendMessage(event)">
            <input type="text" id="messageText" autocomplete="off"/>
            <button>Send</button>
        </form>
        <ul id='messages'>
        </ul>
        <script>
            var ws = new WebSocket("%s");
            ws.onmessage = function(event) {
                var messages = document.getElementById('messages')
                var message = document.createElement('li')
                var content = document.createTextNode(event.data)
                message.appendChild(content)
                messages.appendChild(message)
            };
            function sendMessage(event) {
                var input = document.getElementById("messageText")
                ws.send(input.value)
                input.value = ''
                event.preventDefault()
            }


        </script>
    </body>
</html>
""" % os.environ.get("WEBSOCKET_URL", "ws://localhost:3000")

async def app(scope, receive, send):
    assert scope["type"] in ("http", "websocket")
    if scope["type"] == "http":
        message = await receive()
        if message["type"] == "http.request":
            await send(
                {
                    "type": "http.response.start",
                    "status": 200,
                    "headers": [[b"content-type", b"text/html; charset=utf-8"]],
                }
            )
            await send({"type": "http.response.body", "body": html})
    if scope["type"] == "websocket":
        while True:
            message = await receive()
            if message["type"] == "websocket.connect":
                await send({"type": "websocket.accept"})

            if message["type"] == "websocket.receive":
                text = f"Received message: {message['text']}"
                await send({"type": "websocket.send", "text": text})

            if message["type"] == "websocket.disconnect":
                await send({"type": "websocket.close", "code": 1000})

handler = Mangum(
    app,
    dsn="s3://my-bucket-12345"
)

Project details


Download files

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

Source Distribution

mangum-0.9.0.tar.gz (14.0 kB view hashes)

Uploaded Source

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