Skip to content

Commit 560fe38

Browse files
Don't double-escape query params
1 parent ee785d7 commit 560fe38

File tree

2 files changed

+19
-4
lines changed

2 files changed

+19
-4
lines changed

packages/smithy-http/src/smithy_http/serializers.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -351,7 +351,7 @@ def __init__(
351351
:py:class:`HTTPHeaderTrait` will be checked instead. Required when
352352
collecting list entries.
353353
:param headers: An optional list of header tuples to append to. If not
354-
set, one will be created.
354+
set, one will be created. Values appended will not be escaped.
355355
"""
356356
self.headers: list[tuple[str, str]] = headers if headers is not None else []
357357
self._key = key
@@ -509,7 +509,7 @@ def write_big_decimal(self, schema: Schema, value: Decimal) -> None:
509509

510510
def write_string(self, schema: Schema, value: str) -> None:
511511
key = self._key or schema.expect_trait(HTTPQueryTrait).key
512-
self.query_params.append((key, urlquote(value, safe="")))
512+
self.query_params.append((key, value))
513513

514514
def write_timestamp(self, schema: Schema, value: datetime) -> None:
515515
key = self._key or schema.expect_trait(HTTPQueryTrait).key
@@ -599,7 +599,7 @@ def entry(self, key: str, value_writer: Callable[[ShapeSerializer], None]):
599599

600600

601601
class HTTPQueryMapValueSerializer(SpecificShapeSerializer):
602-
def __init__(self, key: str, query_params: list[tuple[str, str]]) -> None:
602+
def __init__(self, key: str, query_params: list[tuple[str, str]]) -> None:
603603
"""Initialize an HTTPQueryMapValueSerializer.
604604
605605
:param key: The key of the query parameter.
@@ -609,7 +609,8 @@ def __init__(self, key: str, query_params: list[tuple[str, str]]) -> None:
609609
self._query_params = query_params
610610

611611
def write_string(self, schema: Schema, value: str) -> None:
612-
self._query_params.append((self._key, urlquote(value, safe="")))
612+
# Note: values are escaped when query params are joined
613+
self._query_params.append((self._key, value))
613614

614615
@contextmanager
615616
def begin_list(self, schema: Schema, size: int) -> Iterator[ShapeSerializer]:

packages/smithy-http/tests/unit/test_serializers.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1425,6 +1425,20 @@ def query_cases() -> list[HTTPMessageTestCase]:
14251425
)
14261426
),
14271427
),
1428+
HTTPMessageTestCase(
1429+
HTTPQuery(string_member="foo bar"),
1430+
HTTPMessage(destination=URI(host="", path="/", query="string=foo%20bar")),
1431+
),
1432+
HTTPMessageTestCase(
1433+
HTTPQuery(string_list_member=["spam eggs", "eggs spam"]),
1434+
HTTPMessage(
1435+
destination=URI(
1436+
host="",
1437+
path="/",
1438+
query="stringList=spam%20eggs&stringList=eggs%20spam",
1439+
)
1440+
),
1441+
),
14281442
HTTPMessageTestCase(
14291443
HTTPQuery(
14301444
default_timestamp_member=datetime.datetime(2025, 1, 1, tzinfo=UTC)

0 commit comments

Comments
 (0)