def __call__(self, event: AWSMessage, context: AWSMessage) -> AWSMessage: try: response = self.handler(event, context) except Exception as exc: if self.debug: content = traceback.format_exc() return make_response(content, status_code=500) raise exc else: return response
def __call__( self, event: typing.Dict[str, typing.Any], context: typing.Dict[str, typing.Any]) -> typing.Dict[str, typing.Any]: try: response = self.handler(event, context) except Exception as exc: if self.debug: content = traceback.format_exc() return make_response(content, status_code=500) raise exc else: return response
def handle_ws(self, event: dict, context: dict) -> dict: if __ERR__: # pragma: no cover raise ImportError(__ERR__) request_context = event["requestContext"] connection_id = request_context.get("connectionId") domain_name = request_context.get("domainName") stage = request_context.get("stage") event_type = request_context["eventType"] endpoint_url = f"https://{domain_name}/{stage}" if event_type == "CONNECT": # The initial connect event. Parse and store the scope for the connection # in DynamoDB to be retrieved in subsequent message events for this request. server, client = get_server_and_client(event) # The scope headers must be JSON serializable to store in DynamoDB, but # they will be parsed on the MESSAGE event. headers = event.get("headers") or {} root_path = event["requestContext"]["stage"] scope = { "type": "websocket", "path": "/", "headers": headers, "raw_path": None, "root_path": root_path, "scheme": headers.get("X-Forwarded-Proto", "wss"), "query_string": "", "server": server, "client": client, "aws": {"event": event, "context": context}, } connection_table = ConnectionTable() status_code = connection_table.update_item( connection_id, scope=json.dumps(scope) ) if status_code != 200: # pragma: no cover return make_response("Error", status_code=500) return make_response("OK", status_code=200) elif event_type == "MESSAGE": connection_table = ConnectionTable() item = connection_table.get_item(connection_id) if not item: # pragma: no cover return make_response("Error", status_code=500) # Retrieve and deserialize the scope entry created in the connect event for # the current connection. scope = json.loads(item["scope"]) # Ensure the scope definition complies with the ASGI spec. query_string = scope["query_string"] headers = scope["headers"] headers = [[k.encode(), v.encode()] for k, v in headers.items()] query_string = query_string.encode() scope.update({"headers": headers, "query_string": query_string}) asgi_cycle = ASGIWebSocketCycle( scope, endpoint_url=endpoint_url, connection_id=connection_id, connection_table=connection_table, ) asgi_cycle.app_queue.put_nowait({"type": "websocket.connect"}) asgi_cycle.app_queue.put_nowait( { "type": "websocket.receive", "path": "/", "bytes": None, "text": event["body"], } ) try: asgi_cycle(self.app) except ASGIWebSocketCycleException: # pragma: no cover return make_response("Error", status_code=500) return make_response("OK", status_code=200) elif event_type == "DISCONNECT": connection_table = ConnectionTable() status_code = connection_table.delete_item(connection_id) if status_code != 200: # pragma: no cover return make_response("WebSocket disconnect error.", status_code=500) return make_response("OK", status_code=200) return make_response("Error", status_code=500) # pragma: no cover