From eb927327d7480213ab5eb726d2b87e1305c16f63 Mon Sep 17 00:00:00 2001 From: Ruben Fonseca Date: Tue, 13 Feb 2024 22:46:57 +0100 Subject: [PATCH 1/6] fix(event-handler): correctly handle aliased parameters --- .../middlewares/openapi_validation.py | 2 +- .../test_openapi_validation_middleware.py | 23 ++++++++++++++++++- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/aws_lambda_powertools/event_handler/middlewares/openapi_validation.py b/aws_lambda_powertools/event_handler/middlewares/openapi_validation.py index 54c48189282..25ac97ddf89 100644 --- a/aws_lambda_powertools/event_handler/middlewares/openapi_validation.py +++ b/aws_lambda_powertools/event_handler/middlewares/openapi_validation.py @@ -388,7 +388,7 @@ def _normalize_multi_query_string_with_param(query_string: Optional[Dict[str, st try: # if the target parameter is a scalar, we keep the first value of the query string # regardless if there are more in the payload - query_string[param.name] = query_string[param.name][0] + query_string[param.alias] = query_string[param.alias][0] except KeyError: pass return query_string diff --git a/tests/functional/event_handler/test_openapi_validation_middleware.py b/tests/functional/event_handler/test_openapi_validation_middleware.py index 07e2a34ac42..503898df8d6 100644 --- a/tests/functional/event_handler/test_openapi_validation_middleware.py +++ b/tests/functional/event_handler/test_openapi_validation_middleware.py @@ -2,7 +2,7 @@ from dataclasses import dataclass from enum import Enum from pathlib import PurePath -from typing import List, Tuple +from typing import List, Optional, Tuple import pytest from pydantic import BaseModel @@ -15,9 +15,11 @@ Response, VPCLatticeResolver, VPCLatticeV2Resolver, + content_types, ) from aws_lambda_powertools.event_handler.openapi.params import Body, Header, Query from aws_lambda_powertools.shared.types import Annotated +from aws_lambda_powertools.utilities.data_classes import APIGatewayProxyEvent from tests.functional.utils import load_event LOAD_GW_EVENT = load_event("apiGatewayProxyEvent.json") @@ -1018,3 +1020,22 @@ def handler3(): # IF expected_error_text is provided, THEN check for its presence in the response body if expected_error_text: assert any(text in result["body"] for text in expected_error_text) + + +def test_validation_with_alias(): + # GIVEN a Http API V2 proxy type event + app = APIGatewayRestResolver(enable_validation=True) + + class FunkyTown(BaseModel): + parameter: str + + @app.get("/my/path") + def my_path( + parameter: Annotated[Optional[str], Query(alias="parameter1")] = None, + ) -> Response[FunkyTown]: + assert isinstance(app.current_event, APIGatewayProxyEvent) + assert parameter == "value1" + return Response(200, content_types.APPLICATION_JSON, FunkyTown(parameter=parameter)) + + result = app(LOAD_GW_EVENT, {}) + assert result["statusCode"] == 200 From 6d5505321224a2d9628cd03ab75edc08fcaf1701 Mon Sep 17 00:00:00 2001 From: heitorlessa Date: Tue, 25 Jul 2023 14:39:50 +0200 Subject: [PATCH 2/6] fix(parameters): make cache aware of single vs multiple calls Signed-off-by: heitorlessa --- aws_lambda_powertools/utilities/parameters/base.py | 2 +- aws_lambda_powertools/utilities/parameters/types.py | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/aws_lambda_powertools/utilities/parameters/base.py b/aws_lambda_powertools/utilities/parameters/base.py index 710634636d0..411a2520ae9 100644 --- a/aws_lambda_powertools/utilities/parameters/base.py +++ b/aws_lambda_powertools/utilities/parameters/base.py @@ -27,7 +27,7 @@ from aws_lambda_powertools.shared import constants, user_agent from aws_lambda_powertools.shared.functions import resolve_max_age -from aws_lambda_powertools.utilities.parameters.types import TransformOptions +from aws_lambda_powertools.utilities.parameters.types import RecursiveOptions, TransformOptions from .exceptions import GetParameterError, TransformParameterError diff --git a/aws_lambda_powertools/utilities/parameters/types.py b/aws_lambda_powertools/utilities/parameters/types.py index faa06cee89e..a916f1a344d 100644 --- a/aws_lambda_powertools/utilities/parameters/types.py +++ b/aws_lambda_powertools/utilities/parameters/types.py @@ -1,3 +1,4 @@ from aws_lambda_powertools.shared.types import Literal TransformOptions = Literal["json", "binary", "auto", None] +RecursiveOptions = Literal[True, False] From 5a62e753e510ebd610181b81c37ad910b80ded44 Mon Sep 17 00:00:00 2001 From: heitorlessa Date: Tue, 25 Jul 2023 15:16:51 +0200 Subject: [PATCH 3/6] chore: cleanup, add test for single and nested Signed-off-by: heitorlessa --- aws_lambda_powertools/utilities/parameters/base.py | 2 +- aws_lambda_powertools/utilities/parameters/types.py | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/aws_lambda_powertools/utilities/parameters/base.py b/aws_lambda_powertools/utilities/parameters/base.py index 411a2520ae9..710634636d0 100644 --- a/aws_lambda_powertools/utilities/parameters/base.py +++ b/aws_lambda_powertools/utilities/parameters/base.py @@ -27,7 +27,7 @@ from aws_lambda_powertools.shared import constants, user_agent from aws_lambda_powertools.shared.functions import resolve_max_age -from aws_lambda_powertools.utilities.parameters.types import RecursiveOptions, TransformOptions +from aws_lambda_powertools.utilities.parameters.types import TransformOptions from .exceptions import GetParameterError, TransformParameterError diff --git a/aws_lambda_powertools/utilities/parameters/types.py b/aws_lambda_powertools/utilities/parameters/types.py index a916f1a344d..faa06cee89e 100644 --- a/aws_lambda_powertools/utilities/parameters/types.py +++ b/aws_lambda_powertools/utilities/parameters/types.py @@ -1,4 +1,3 @@ from aws_lambda_powertools.shared.types import Literal TransformOptions = Literal["json", "binary", "auto", None] -RecursiveOptions = Literal[True, False] From f79dffcfedf7f5f97509da2e4eb253c559f00f75 Mon Sep 17 00:00:00 2001 From: heitorlessa Date: Thu, 15 Feb 2024 09:49:57 +0100 Subject: [PATCH 4/6] chore: no-op exception suppress Signed-off-by: heitorlessa --- .../event_handler/middlewares/openapi_validation.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/aws_lambda_powertools/event_handler/middlewares/openapi_validation.py b/aws_lambda_powertools/event_handler/middlewares/openapi_validation.py index 25ac97ddf89..fe42b8cd7c4 100644 --- a/aws_lambda_powertools/event_handler/middlewares/openapi_validation.py +++ b/aws_lambda_powertools/event_handler/middlewares/openapi_validation.py @@ -1,3 +1,4 @@ +import contextlib import dataclasses import json import logging @@ -385,12 +386,10 @@ def _normalize_multi_query_string_with_param(query_string: Optional[Dict[str, st """ if query_string: for param in filter(is_scalar_field, params): - try: + with contextlib.suppress(KeyError): # if the target parameter is a scalar, we keep the first value of the query string # regardless if there are more in the payload query_string[param.alias] = query_string[param.alias][0] - except KeyError: - pass return query_string From 2ee07b64386bd57193ee67f8c177d008035d444c Mon Sep 17 00:00:00 2001 From: heitorlessa Date: Thu, 15 Feb 2024 09:55:06 +0100 Subject: [PATCH 5/6] fix: use local event, not global to prevent race condition Signed-off-by: heitorlessa --- .../event_handler/test_openapi_validation_middleware.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/functional/event_handler/test_openapi_validation_middleware.py b/tests/functional/event_handler/test_openapi_validation_middleware.py index 503898df8d6..be3a13dd656 100644 --- a/tests/functional/event_handler/test_openapi_validation_middleware.py +++ b/tests/functional/event_handler/test_openapi_validation_middleware.py @@ -1025,6 +1025,7 @@ def handler3(): def test_validation_with_alias(): # GIVEN a Http API V2 proxy type event app = APIGatewayRestResolver(enable_validation=True) + event = load_event("apiGatewayProxyEvent.json") class FunkyTown(BaseModel): parameter: str @@ -1037,5 +1038,5 @@ def my_path( assert parameter == "value1" return Response(200, content_types.APPLICATION_JSON, FunkyTown(parameter=parameter)) - result = app(LOAD_GW_EVENT, {}) + result = app(event, {}) assert result["statusCode"] == 200 From a2da6b1f6ec9da3ce8b76e7f1a16e43dba4bcd67 Mon Sep 17 00:00:00 2001 From: heitorlessa Date: Thu, 15 Feb 2024 09:56:25 +0100 Subject: [PATCH 6/6] Revert "chore: no-op exception suppress" This reverts commit f79dffcfedf7f5f97509da2e4eb253c559f00f75. --- .../event_handler/middlewares/openapi_validation.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/aws_lambda_powertools/event_handler/middlewares/openapi_validation.py b/aws_lambda_powertools/event_handler/middlewares/openapi_validation.py index fe42b8cd7c4..25ac97ddf89 100644 --- a/aws_lambda_powertools/event_handler/middlewares/openapi_validation.py +++ b/aws_lambda_powertools/event_handler/middlewares/openapi_validation.py @@ -1,4 +1,3 @@ -import contextlib import dataclasses import json import logging @@ -386,10 +385,12 @@ def _normalize_multi_query_string_with_param(query_string: Optional[Dict[str, st """ if query_string: for param in filter(is_scalar_field, params): - with contextlib.suppress(KeyError): + try: # if the target parameter is a scalar, we keep the first value of the query string # regardless if there are more in the payload query_string[param.alias] = query_string[param.alias][0] + except KeyError: + pass return query_string