diff --git a/openapi_core/contrib/falcon/requests.py b/openapi_core/contrib/falcon/requests.py index 6ef5033e..7e1fe1cf 100644 --- a/openapi_core/contrib/falcon/requests.py +++ b/openapi_core/contrib/falcon/requests.py @@ -11,6 +11,7 @@ from werkzeug.datastructures import Headers from werkzeug.datastructures import ImmutableMultiDict +from openapi_core.contrib.falcon.util import unpack_params from openapi_core.datatypes import RequestParameters @@ -29,7 +30,7 @@ def __init__( # Path gets deduced by path finder against spec self.parameters = RequestParameters( - query=ImmutableMultiDict(list(self.request.params.items())), + query=ImmutableMultiDict(unpack_params(self.request.params)), header=Headers(self.request.headers), cookie=self.request.cookies, ) diff --git a/openapi_core/contrib/falcon/util.py b/openapi_core/contrib/falcon/util.py new file mode 100644 index 00000000..0f651e42 --- /dev/null +++ b/openapi_core/contrib/falcon/util.py @@ -0,0 +1,15 @@ +from typing import Any +from typing import Dict +from typing import Generator +from typing import Tuple + + +def unpack_params( + params: Dict[str, Any] +) -> Generator[Tuple[str, Any], None, None]: + for k, v in params.items(): + if isinstance(v, list): + for v2 in v: + yield (k, v2) + else: + yield (k, v) diff --git a/tests/integration/contrib/falcon/data/v3.0/falconproject/pets/resources.py b/tests/integration/contrib/falcon/data/v3.0/falconproject/pets/resources.py index 5d0a83f4..d6e903da 100644 --- a/tests/integration/contrib/falcon/data/v3.0/falconproject/pets/resources.py +++ b/tests/integration/contrib/falcon/data/v3.0/falconproject/pets/resources.py @@ -11,11 +11,19 @@ class PetListResource: def on_get(self, request, response): assert request.context.openapi assert not request.context.openapi.errors - assert request.context.openapi.parameters.query == { - "page": 1, - "limit": 12, - "search": "", - } + if "ids" in request.params: + assert request.context.openapi.parameters.query == { + "page": 1, + "limit": 2, + "search": "", + "ids": [1, 2], + } + else: + assert request.context.openapi.parameters.query == { + "page": 1, + "limit": 12, + "search": "", + } data = [ { "id": 12, diff --git a/tests/integration/contrib/falcon/test_falcon_project.py b/tests/integration/contrib/falcon/test_falcon_project.py index 7ed3a19c..69e11974 100644 --- a/tests/integration/contrib/falcon/test_falcon_project.py +++ b/tests/integration/contrib/falcon/test_falcon_project.py @@ -67,6 +67,33 @@ def test_get_valid(self, client): ], } + def test_get_valid_multiple_ids(self, client): + headers = { + "Content-Type": "application/json", + } + query_string = "limit=2&ids=1&ids=2" + + with pytest.warns(DeprecationWarning): + response = client.simulate_get( + "/v1/pets", + host="petstore.swagger.io", + headers=headers, + query_string=query_string, + ) + + assert response.status_code == 200 + assert response.json == { + "data": [ + { + "id": 12, + "name": "Cat", + "ears": { + "healthy": True, + }, + }, + ], + } + def test_post_server_invalid(self, client): response = client.simulate_post( "/v1/pets",