Skip to content

Commit 7fc9efb

Browse files
fix(data_class): merge querystring parameters in ALB/APIGW classes (#8154)
fix(data_class): merge querystring parameters
1 parent cd8829b commit 7fc9efb

File tree

4 files changed

+86
-2
lines changed

4 files changed

+86
-2
lines changed

aws_lambda_powertools/utilities/data_classes/alb_event.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,17 @@ def request_context(self) -> ALBEventRequestContext:
4444

4545
@property
4646
def resolved_query_string_parameters(self) -> dict[str, list[str]]:
47-
params = self.multi_value_query_string_parameters or super().resolved_query_string_parameters
47+
multi_value = self.multi_value_query_string_parameters
48+
single_value = super().resolved_query_string_parameters
49+
50+
if not multi_value:
51+
params = single_value
52+
elif not single_value:
53+
params = multi_value
54+
else:
55+
# Merge both: multi_value takes precedence, single_value fills missing keys
56+
params = {**single_value, **multi_value}
57+
4858
if not self.decode_query_parameters:
4959
return params
5060

aws_lambda_powertools/utilities/data_classes/api_gateway_proxy_event.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,17 @@ def multi_value_headers(self) -> dict[str, list[str]]:
120120

121121
@property
122122
def resolved_query_string_parameters(self) -> dict[str, list[str]]:
123-
return self.multi_value_query_string_parameters or super().resolved_query_string_parameters
123+
multi_value = self.multi_value_query_string_parameters
124+
single_value = super().resolved_query_string_parameters
125+
126+
if not multi_value:
127+
return single_value
128+
129+
if not single_value:
130+
return multi_value
131+
132+
# Merge both: multi_value takes precedence, single_value fills missing keys
133+
return {**single_value, **multi_value}
124134

125135
@property
126136
def resolved_headers_field(self) -> dict[str, Any]:

tests/unit/data_classes/required_dependencies/test_alb_event.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,3 +52,17 @@ def test_alb_event_decode_multi_value_query_parameters():
5252
# With decode_query_parameters, the key and value are not decoded
5353
parsed_event.decode_query_parameters = True
5454
assert parsed_event.resolved_query_string_parameters == {expected_key: expected_values}
55+
56+
57+
def test_alb_event_merged_query_string_parameters():
58+
"""When both multiValueQueryStringParameters and queryStringParameters are present,
59+
resolved_query_string_parameters should merge them (GH #7993)."""
60+
raw_event = load_event("albMultiValueQueryStringEvent.json")
61+
raw_event["multiValueQueryStringParameters"] = {"ids": ["1", "2", "3"]}
62+
raw_event["queryStringParameters"] = {"status": "fizzbuzz"}
63+
64+
parsed_event = ALBEvent(raw_event)
65+
resolved = parsed_event.resolved_query_string_parameters
66+
67+
assert resolved["ids"] == ["1", "2", "3"]
68+
assert resolved["status"] == ["fizzbuzz"]

tests/unit/data_classes/required_dependencies/test_api_gateway_proxy_event.py

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,3 +241,53 @@ def test_api_gateway_proxy_v2_iam_event():
241241
assert iam.principal_org_id == iam_raw["principalOrgId"]
242242
assert iam.user_arn == iam_raw["userArn"]
243243
assert iam.user_id == iam_raw["userId"]
244+
245+
246+
def test_api_gateway_proxy_event_merged_query_string_parameters():
247+
"""When both multiValueQueryStringParameters and queryStringParameters are present,
248+
resolved_query_string_parameters should merge them (GH #7993)."""
249+
raw_event = load_event("apiGatewayProxyEvent.json")
250+
raw_event["multiValueQueryStringParameters"] = {"ids": ["1", "2", "3"]}
251+
raw_event["queryStringParameters"] = {"status": "fizzbuzz"}
252+
253+
parsed_event = APIGatewayProxyEvent(raw_event)
254+
resolved = parsed_event.resolved_query_string_parameters
255+
256+
assert resolved["ids"] == ["1", "2", "3"]
257+
assert resolved["status"] == ["fizzbuzz"]
258+
259+
260+
def test_api_gateway_proxy_event_multi_value_takes_precedence():
261+
"""When the same key exists in both, multiValueQueryStringParameters wins."""
262+
raw_event = load_event("apiGatewayProxyEvent.json")
263+
raw_event["multiValueQueryStringParameters"] = {"key": ["a", "b"]}
264+
raw_event["queryStringParameters"] = {"key": "c"}
265+
266+
parsed_event = APIGatewayProxyEvent(raw_event)
267+
resolved = parsed_event.resolved_query_string_parameters
268+
269+
assert resolved["key"] == ["a", "b"]
270+
271+
272+
def test_api_gateway_proxy_event_only_single_value_query_params():
273+
"""When only queryStringParameters is present, it should still work."""
274+
raw_event = load_event("apiGatewayProxyEvent.json")
275+
raw_event["multiValueQueryStringParameters"] = None
276+
raw_event["queryStringParameters"] = {"status": "active"}
277+
278+
parsed_event = APIGatewayProxyEvent(raw_event)
279+
resolved = parsed_event.resolved_query_string_parameters
280+
281+
assert resolved["status"] == ["active"]
282+
283+
284+
def test_api_gateway_proxy_event_only_multi_value_query_params():
285+
"""When only multiValueQueryStringParameters is present, it should still work."""
286+
raw_event = load_event("apiGatewayProxyEvent.json")
287+
raw_event["multiValueQueryStringParameters"] = {"ids": ["1", "2"]}
288+
raw_event["queryStringParameters"] = None
289+
290+
parsed_event = APIGatewayProxyEvent(raw_event)
291+
resolved = parsed_event.resolved_query_string_parameters
292+
293+
assert resolved["ids"] == ["1", "2"]

0 commit comments

Comments
 (0)