From 35e7745952a424878dc58c9d9614199e20cd8b3f Mon Sep 17 00:00:00 2001 From: Heitor Lessa Date: Fri, 23 Jul 2021 21:25:50 +0200 Subject: [PATCH] fix(apigw): route regression for non-word and unsafe URI chars (#556) --- .../event_handler/api_gateway.py | 6 ++++- .../event_handler/test_api_gateway.py | 27 +++++++++++++++++++ 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/aws_lambda_powertools/event_handler/api_gateway.py b/aws_lambda_powertools/event_handler/api_gateway.py index 6948646a360..44d3f2b07de 100644 --- a/aws_lambda_powertools/event_handler/api_gateway.py +++ b/aws_lambda_powertools/event_handler/api_gateway.py @@ -21,7 +21,11 @@ logger = logging.getLogger(__name__) _DYNAMIC_ROUTE_PATTERN = r"(<\w+>)" -_NAMED_GROUP_BOUNDARY_PATTERN = r"(?P\1\\w+\\b)" +_SAFE_URI = "-._~()'!*:@,;" # https://www.ietf.org/rfc/rfc3986.txt +# API GW/ALB decode non-safe URI chars; we must support them too +_UNSAFE_URI = "%<>\[\]{}|^" # noqa: W605 + +_NAMED_GROUP_BOUNDARY_PATTERN = fr"(?P\1[{_SAFE_URI}{_UNSAFE_URI}\\w]+)" class ProxyEventType(Enum): diff --git a/tests/functional/event_handler/test_api_gateway.py b/tests/functional/event_handler/test_api_gateway.py index 1c7c53f7187..f16086ba634 100644 --- a/tests/functional/event_handler/test_api_gateway.py +++ b/tests/functional/event_handler/test_api_gateway.py @@ -701,3 +701,30 @@ def get_network_account(account_id: str, network_id: str): event["resource"] = "/accounts/{account_id}/source_networks/{network_id}" event["path"] = "/accounts/nested_account/source_networks/network" app.resolve(event, {}) + + +@pytest.mark.parametrize( + "req", + [ + pytest.param(123456789, id="num"), + pytest.param("user@example.com", id="email"), + pytest.param("-._~'!*:@,;()", id="safe-rfc3986"), + pytest.param("%<>[]{}|^", id="unsafe-rfc3986"), + ], +) +def test_non_word_chars_route(req): + # GIVEN + app = ApiGatewayResolver() + event = deepcopy(LOAD_GW_EVENT) + + # WHEN + @app.get("/accounts/") + def get_account(account_id: str): + assert account_id == f"{req}" + + # THEN + event["resource"] = "/accounts/{account_id}" + event["path"] = f"/accounts/{req}" + + ret = app.resolve(event, None) + assert ret["statusCode"] == 200