Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 37 additions & 3 deletions mangum/handlers/aws_alb.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,42 @@ class AwsAlb(AbstractHandler):

TYPE = "AWS_ALB"

def encode_query_string(self) -> bytes:
"""
Encodes the queryStringParameters.
The parameters must be decoded, and then encoded again to prevent double
encoding.

https://docs.aws.amazon.com/elasticloadbalancing/latest/application/lambda-functions.html # noqa: E501
"If the query parameters are URL-encoded, the load balancer does not decode
them. You must decode them in your Lambda function."

Issue: https://github.com/jordaneremieff/mangum/issues/178
"""

params = self.trigger_event.get("multiValueQueryStringParameters")
if not params:
params = self.trigger_event.get("queryStringParameters")
if not params:
return b"" # No query parameters, exit early with an empty byte string.

# Loop through the query parameters, unquote each key and value and append the
# pair as a tuple to the query list. If value is a list or a tuple, loop
# through the nested struture and unqote.
query = []
for key, value in params.items():
if isinstance(value, (tuple, list)):
for v in value:
query.append(
(urllib.parse.unquote_plus(key), urllib.parse.unquote_plus(v))
)
else:
query.append(
(urllib.parse.unquote_plus(key), urllib.parse.unquote_plus(value))
)

return urllib.parse.urlencode(query).encode()

@property
def request(self) -> Request:
event = self.trigger_event
Expand All @@ -27,9 +63,7 @@ def request(self) -> Request:
source_ip = headers.get("x-forwarded-for", "")
path = event["path"]
http_method = event["httpMethod"]
query_string = urllib.parse.urlencode(
event.get("queryStringParameters", {}), doseq=True
).encode()
query_string = self.encode_query_string()

server_name = headers.get("host", "mangum")
if ":" not in server_name:
Expand Down
12 changes: 9 additions & 3 deletions tests/handlers/test_aws_alb.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ def get_mock_aws_alb_event(
},
"httpMethod": method,
"path": path,
"queryStringParameters": multi_value_query_parameters
"multiValueQueryStringParameters": multi_value_query_parameters
if multi_value_query_parameters
else {},
"headers": {
Expand Down Expand Up @@ -52,7 +52,13 @@ def test_aws_alb_basic():
},
"httpMethod": "GET",
"path": "/lambda",
"queryStringParameters": {"query": "1234ABCD"},
"queryStringParameters": {
"q1": "1234ABCD",
"q2": "b c", # not encoded
"q3": "b%20c", # encoded
"q4": "/some/path/", # not encoded
"q5": "%2Fsome%2Fpath%2F", # encoded
},
"headers": {
"accept": "text/html,application/xhtml+xml,application/xml;q=0.9,"
"image/webp,image/apng,*/*;q=0.8",
Expand Down Expand Up @@ -107,7 +113,7 @@ def test_aws_alb_basic():
"http_version": "1.1",
"method": "GET",
"path": "/lambda",
"query_string": b"query=1234ABCD",
"query_string": b"q1=1234ABCD&q2=b+c&q3=b+c&q4=%2Fsome%2Fpath%2F&q5=%2Fsome%2Fpath%2F", # noqa: E501
"raw_path": None,
"root_path": "",
"scheme": "http",
Expand Down