Skip to content

Commit 2b72123

Browse files
Don't double-escape query params
1 parent 6160569 commit 2b72123

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
@@ -328,7 +328,7 @@ def __init__(
328328
:py:class:`HTTPHeaderTrait` will be checked instead. Required when
329329
collecting list entries.
330330
:param headers: An optional list of header tuples to append to. If not
331-
set, one will be created.
331+
set, one will be created. Values appended will not be escaped.
332332
"""
333333
self.headers: list[tuple[str, str]] = headers if headers is not None else []
334334
self._key = key
@@ -486,7 +486,7 @@ def write_big_decimal(self, schema: Schema, value: Decimal) -> None:
486486

487487
def write_string(self, schema: Schema, value: str) -> None:
488488
key = self._key or schema.expect_trait(HTTPQueryTrait).key
489-
self.query_params.append((key, urlquote(value, safe="")))
489+
self.query_params.append((key, value))
490490

491491
def write_timestamp(self, schema: Schema, value: datetime) -> None:
492492
key = self._key or schema.expect_trait(HTTPQueryTrait).key
@@ -576,7 +576,7 @@ def entry(self, key: str, value_writer: Callable[[ShapeSerializer], None]):
576576

577577

578578
class HTTPQueryMapValueSerializer(SpecificShapeSerializer):
579-
def __init__(self, key: str, query_params: list[tuple[str, str]]) -> None:
579+
def __init__(self, key: str, query_params: list[tuple[str, str]]) -> None:
580580
"""Initialize an HTTPQueryMapValueSerializer.
581581
582582
:param key: The key of the query parameter.
@@ -586,7 +586,8 @@ def __init__(self, key: str, query_params: list[tuple[str, str]]) -> None:
586586
self._query_params = query_params
587587

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

591592
@contextmanager
592593
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
@@ -1381,6 +1381,20 @@ def query_cases() -> list[HTTPMessageTestCase]:
13811381
)
13821382
),
13831383
),
1384+
HTTPMessageTestCase(
1385+
HTTPQuery(string_member="foo bar"),
1386+
HTTPMessage(destination=URI(host="", path="/", query="string=foo%20bar")),
1387+
),
1388+
HTTPMessageTestCase(
1389+
HTTPQuery(string_list_member=["spam eggs", "eggs spam"]),
1390+
HTTPMessage(
1391+
destination=URI(
1392+
host="",
1393+
path="/",
1394+
query="stringList=spam%20eggs&stringList=eggs%20spam",
1395+
)
1396+
),
1397+
),
13841398
HTTPMessageTestCase(
13851399
HTTPQuery(
13861400
default_timestamp_member=datetime.datetime(2025, 1, 1, tzinfo=UTC)

0 commit comments

Comments
 (0)