From e40948fde3d822bb8d4bd8efbd6219ebcf3992ed Mon Sep 17 00:00:00 2001 From: "F. St" <39712181+Feriixu@users.noreply.github.com> Date: Fri, 4 Feb 2022 15:53:50 +0100 Subject: [PATCH] Fix aws_api_gateway handler not accepting combined headers and multiValueHeaders (#229) * Fix aws_api_gateway handler not accepting combined headers and multiValueHeaders * Fix test_aws_api_gateway.py::test_aws_api_gateway_scope_basic * Formatting * Fix test_aws_api_gateway_scope_basic again There was a single space where there shouldn't have been one, so the assert failed. * More reformatting Lines were too long * Okay now the linters should be happy --- mangum/handlers/aws_api_gateway.py | 26 ++++++++++++--------- tests/handlers/test_aws_api_gateway.py | 31 ++++++++++++++++++++------ 2 files changed, 40 insertions(+), 17 deletions(-) diff --git a/mangum/handlers/aws_api_gateway.py b/mangum/handlers/aws_api_gateway.py index a9edab40..c20558f2 100644 --- a/mangum/handlers/aws_api_gateway.py +++ b/mangum/handlers/aws_api_gateway.py @@ -35,17 +35,23 @@ def __init__( def request(self) -> Request: event = self.trigger_event - # multiValue versions of headers take precedence over their plain versions - # https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-lambda-proxy-integrations.html#api-gateway-simple-proxy-for-lambda-input-format + # See this for more info on headers: + # https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-lambda-proxy-integrations.html#apigateway-multivalue-headers-and-parameters + headers = {} + # Read headers + if event.get("headers"): + headers.update({k.lower(): v for k, v in event.get("headers", {}).items()}) + # Read multiValueHeaders + # This overrides headers that have the same name + # That means that multiValue versions of headers take precedence + # over their plain versions if event.get("multiValueHeaders"): - headers = { - k.lower(): ", ".join(v) if isinstance(v, list) else "" - for k, v in event.get("multiValueHeaders", {}).items() - } - elif event.get("headers"): - headers = {k.lower(): v for k, v in event.get("headers", {}).items()} - else: - headers = {} + headers.update( + { + k.lower(): ", ".join(v) if isinstance(v, list) else "" + for k, v in event.get("multiValueHeaders", {}).items() + } + ) request_context = event["requestContext"] diff --git a/tests/handlers/test_aws_api_gateway.py b/tests/handlers/test_aws_api_gateway.py index f5a8c1a4..eac4a2d3 100644 --- a/tests/handlers/test_aws_api_gateway.py +++ b/tests/handlers/test_aws_api_gateway.py @@ -47,7 +47,9 @@ def get_mock_aws_api_gateway_event( "cognitoAuthenticationType": "", "cognitoAuthenticationProvider": "", "userArn": "", - "userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.82 Safari/537.36 OPR/39.0.2256.48", # noqa: E501 + "userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) " + "AppleWebKit/537.36 (KHTML, like Gecko) " + "Chrome/52.0.2743.82 Safari/537.36 OPR/39.0.2256.48", "user": "", }, "resourcePath": "/{proxy+}", @@ -75,15 +77,21 @@ def test_aws_api_gateway_scope_basic(): "httpMethod": "GET", "requestContext": {"resourcePath": "/", "httpMethod": "GET", "path": "/Prod/"}, "headers": { - "accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9", # noqa: E501 + "accept": "text/html,application/xhtml+xml,application/xml;" + "q=0.9,image/webp,image/apng,*/*;q=0.8," + "application/signed-exchange;v=b3;q=0.9", "accept-encoding": "gzip, deflate, br", "Host": "70ixmpl4fl.execute-api.us-east-2.amazonaws.com", - "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.132 Safari/537.36", # noqa: E501 + "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) " + "AppleWebKit/537.36 (KHTML, like Gecko) " + "Chrome/80.0.3987.132 Safari/537.36", "X-Amzn-Trace-Id": "Root=1-5e66d96f-7491f09xmpl79d18acf3d050", }, "multiValueHeaders": { "accept": [ - "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9" # noqa: E501 + "text/html,application/xhtml+xml,application/xml;" + "q=0.9,image/webp,image/apng,*/*;q=0.8," + "application/signed-exchange;v=b3;q=0.9" ], "accept-encoding": ["gzip, deflate, br"], }, @@ -107,11 +115,20 @@ def test_aws_api_gateway_scope_basic(): "headers": [ [ b"accept", - b"text/html,application/xhtml+xml,application/xml;q=0.9," - b"image/webp,image/apng,*/*;q=0.8," + b"text/html,application/xhtml+xml,application/xml;" + b"q=0.9,image/webp,image/apng,*/*;q=0.8," b"application/signed-exchange;v=b3;q=0.9", ], [b"accept-encoding", b"gzip, deflate, br"], + [b"host", b"70ixmpl4fl.execute-api.us-east-2.amazonaws.com"], + [ + b"user-agent", + b"Mozilla/5.0 (Windows NT 10.0; Win64; x64) " + b"AppleWebKit/537.36 (KHTML, like Gecko) " + b"Chrome/80.0.3987.132 " + b"Safari/537.36", + ], + [b"x-amzn-trace-id", b"Root=1-5e66d96f-7491f09xmpl79d18acf3d050"], ], "http_version": "1.1", "method": "GET", @@ -120,7 +137,7 @@ def test_aws_api_gateway_scope_basic(): "raw_path": None, "root_path": "", "scheme": "https", - "server": ("mangum", 80), + "server": ("70ixmpl4fl.execute-api.us-east-2.amazonaws.com", 80), "type": "http", }