Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(parse_query_string): change the default value of csv to False #2200

Merged
merged 5 commits into from
Dec 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 6 additions & 0 deletions docs/_newsfragments/1999.breakingchange.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
The default value of the ``csv`` parameter in
:func:`~falcon.uri.parse_query_string` was changed to ``False``, matching the
default behavior of other parts of the framework (such as
:attr:`req.params <falcon.Request.params>`, the test client, etc).
If the old behavior fits your use case better, pass the ``csv=True`` keyword
argument explicitly.
2 changes: 1 addition & 1 deletion falcon/cyutil/uri.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,7 @@ cdef cy_parse_query_string(unsigned char* data, Py_ssize_t length,


def parse_query_string(unicode query_string not None, bint keep_blank=False,
bint csv=True):
bint csv=False):
cdef bytes byte_string = query_string.encode('utf-8')
cdef unsigned char* data = byte_string
return cy_parse_query_string(data, len(byte_string), keep_blank, csv)
Expand Down
19 changes: 11 additions & 8 deletions falcon/util/uri.py
Original file line number Diff line number Diff line change
Expand Up @@ -337,20 +337,22 @@ def decode(encoded_uri: str, unquote_plus: bool = True) -> str:


def parse_query_string(
query_string: str, keep_blank: bool = False, csv: bool = True
query_string: str, keep_blank: bool = False, csv: bool = False
) -> Dict[str, Union[str, List[str]]]:
"""Parse a query string into a dict.

Query string parameters are assumed to use standard form-encoding. Only
parameters with values are returned. For example, given 'foo=bar&flag',
this function would ignore 'flag' unless the `keep_blank_qs_values` option
this function would ignore 'flag' unless the `keep_blank` option
is set.

Note:
In addition to the standard HTML form-based method for specifying
lists by repeating a given param multiple times, Falcon supports
a more compact form in which the param may be given a single time
but set to a ``list`` of comma-separated elements (e.g., 'foo=a,b,c').
This comma-separated format can be enabled by setting the `csv`
option (see below) to ``True``.

When using this format, all commas uri-encoded will not be treated by
Falcon as a delimiter. If the client wants to send a value as a list,
Expand All @@ -365,12 +367,13 @@ def parse_query_string(
they do not have a value (default ``False``). For comma-separated
values, this option also determines whether or not empty elements
in the parsed list are retained.
csv: Set to ``False`` in order to disable splitting query
parameters on ``,`` (default ``True``). Depending on the user agent,
encoding lists as multiple occurrences of the same parameter might
be preferable. In this case, setting `parse_qs_csv` to ``False``
will cause the framework to treat commas as literal characters in
each occurring parameter value.
csv: Set to ``True`` in order to enable splitting query
parameters on ``,`` (default ``False``).
Depending on the user agent, encoding lists as multiple occurrences
of the same parameter might be preferable. In this case, keeping
`parse_qs_csv` at its default value (``False``) will cause the
framework to treat commas as literal characters in each occurring
parameter value.

Returns:
dict: A dictionary of (*name*, *value*) pairs, one per query
Expand Down
15 changes: 12 additions & 3 deletions tests/test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -380,13 +380,13 @@ def test_parse_query_string(self):
result = uri.parse_query_string(query_string)
assert result['a'] == decoded_url
assert result['b'] == decoded_json
assert result['c'] == ['1', '2', '3']
assert result['c'] == '1,2,3'
CaselIT marked this conversation as resolved.
Show resolved Hide resolved
assert result['d'] == 'test'
assert result['e'] == ['a', '&=,']
assert result['e'] == 'a,,&=,'
assert result['f'] == ['a', 'a=b']
assert result['é'] == 'a=b'

result = uri.parse_query_string(query_string, True)
result = uri.parse_query_string(query_string, True, True)
assert result['a'] == decoded_url
assert result['b'] == decoded_json
assert result['c'] == ['1', '2', '3']
Expand All @@ -395,6 +395,15 @@ def test_parse_query_string(self):
assert result['f'] == ['a', 'a=b']
assert result['é'] == 'a=b'

result = uri.parse_query_string(query_string, csv=True)
assert result['a'] == decoded_url
assert result['b'] == decoded_json
assert result['c'] == ['1', '2', '3']
assert result['d'] == 'test'
assert result['e'] == ['a', '&=,']
assert result['f'] == ['a', 'a=b']
assert result['é'] == 'a=b'

@pytest.mark.parametrize(
'query_string,keep_blank,expected',
[
Expand Down