diff --git a/slack_bolt/adapter/aws_lambda/handler.py b/slack_bolt/adapter/aws_lambda/handler.py index 4d155e58f..270d48831 100644 --- a/slack_bolt/adapter/aws_lambda/handler.py +++ b/slack_bolt/adapter/aws_lambda/handler.py @@ -71,22 +71,22 @@ def handle(self, event, context): def to_bolt_request(event) -> BoltRequest: - body = event.get("body", "") - if event["isBase64Encoded"]: + body = event.get("body") or "" + if event.get("isBase64Encoded") is True and body: body = base64.b64decode(body).decode("utf-8") - cookies: Sequence[str] = event.get("cookies", []) - if cookies is None or len(cookies) == 0: + cookies: Sequence[str] = event.get("cookies") or [] + if len(cookies) == 0: # In the case of format v1 - multiValueHeaders = event.get("multiValueHeaders", {}) - cookies = multiValueHeaders.get("cookie", []) + multiValueHeaders = event.get("multiValueHeaders") or {} + cookies = multiValueHeaders.get("cookie") or [] if len(cookies) == 0: # Try using uppercase - cookies = multiValueHeaders.get("Cookie", []) - headers = event.get("headers", {}) + cookies = multiValueHeaders.get("Cookie") or [] + headers = dict(event.get("headers") or {}) headers["cookie"] = cookies return BoltRequest( body=body, - query=event.get("queryStringParameters", {}), + query=event.get("queryStringParameters") or {}, headers=headers, ) diff --git a/tests/adapter_tests/aws/test_aws_lambda.py b/tests/adapter_tests/aws/test_aws_lambda.py index c2e888fb7..3827af9b8 100644 --- a/tests/adapter_tests/aws/test_aws_lambda.py +++ b/tests/adapter_tests/aws/test_aws_lambda.py @@ -1,3 +1,4 @@ +import base64 import json from time import time from urllib.parse import quote @@ -70,6 +71,55 @@ def test_not_found(self): response = not_found() assert response["statusCode"] == 404 + def test_null_fields_in_api_gateway_event(self): + app = App(client=self.web_client, signing_secret=self.signing_secret) + event = { + "httpMethod": "POST", + "requestContext": {"httpMethod": "POST"}, + "headers": None, + "multiValueHeaders": None, + "queryStringParameters": None, + "body": "{}", + "isBase64Encoded": False, + } + response = SlackRequestHandler(app).handle(event, self.context) + assert response["statusCode"] == 401 + assert event["headers"] is None + + def test_missing_is_base64_encoded_and_null_body(self): + app = App(client=self.web_client, signing_secret=self.signing_secret) + event = {"requestContext": {"http": {"method": "POST"}}, "headers": {}, "body": "{}"} + assert SlackRequestHandler(app).handle(event, self.context)["statusCode"] == 401 + event = {"requestContext": {"http": {"method": "POST"}}, "headers": {}, "body": None, "isBase64Encoded": True} + assert SlackRequestHandler(app).handle(event, self.context)["statusCode"] == 401 + + def test_base64_encoded_body(self): + app = App(client=self.web_client, signing_secret=self.signing_secret) + + def event_handler(): + pass + + app.event("app_mention")(event_handler) + input = { + "token": "verification_token", + "team_id": "T111", + "api_app_id": "A111", + "event": {"type": "app_mention", "text": "<@W111> Hi", "user": "W222", "team": "T111", "channel": "C111"}, + "type": "event_callback", + "event_id": "Ev111", + "event_time": 1595926230, + } + timestamp, body = str(int(time())), json.dumps(input) + event = { + "body": base64.b64encode(body.encode("utf-8")).decode("ascii"), + "queryStringParameters": None, + "headers": self.build_headers(timestamp, body), + "requestContext": {"http": {"method": "POST"}}, + "isBase64Encoded": True, + } + response = SlackRequestHandler(app).handle(event, self.context) + assert response["statusCode"] == 200 + def test_first_value(self): assert _first_value({"foo": [1, 2, 3]}, "foo") == 1 assert _first_value({"foo": []}, "foo") is None