From 52106edb722f7c07aae3b731cc695ccbdcf08426 Mon Sep 17 00:00:00 2001 From: Lyonnet Date: Fri, 18 Oct 2024 15:40:46 +0800 Subject: [PATCH] bugfix: keep blank parameters in query string, close #411 --- .github/workflows/build-and-test.yaml | 1 - curl_cffi/requests/session.py | 4 ++-- tests/unittest/conftest.py | 2 +- tests/unittest/test_requests.py | 12 ++++++++++++ 4 files changed, 15 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build-and-test.yaml b/.github/workflows/build-and-test.yaml index e1f8587..1ad86b0 100644 --- a/.github/workflows/build-and-test.yaml +++ b/.github/workflows/build-and-test.yaml @@ -39,7 +39,6 @@ jobs: with: path: ./dist/*.tar.gz overwrite: true - - uses: actions/setup-python@v5 with: python-version: '3.10' diff --git a/curl_cffi/requests/session.py b/curl_cffi/requests/session.py index 9edbcef..a66173b 100644 --- a/curl_cffi/requests/session.py +++ b/curl_cffi/requests/session.py @@ -109,7 +109,7 @@ def _is_absolute_url(url: str) -> bool: def _quote_path_and_params(url: str, quote_str: str = ""): safe = "".join(SAFE_CHARS - set(quote_str)) parsed_url = urlparse(url) - parsed_get_args = parse_qsl(parsed_url.query) + parsed_get_args = parse_qsl(parsed_url.query, keep_blank_values=True) encoded_get_args = urlencode(parsed_get_args, doseq=True, safe=safe) return ParseResult( parsed_url.scheme, @@ -141,7 +141,7 @@ def _update_url_params(url: str, params: Union[Dict, List, Tuple]) -> str: parsed_url = urlparse(url) # Extracting URL arguments from parsed URL, NOTE the result is a list, not dict - parsed_get_args = parse_qsl(parsed_url.query) + parsed_get_args = parse_qsl(parsed_url.query, keep_blank_values=True) # Merging URL arguments dict with new params old_args_counter = Counter(x[0] for x in parsed_get_args) diff --git a/tests/unittest/conftest.py b/tests/unittest/conftest.py index bf47600..8751b74 100644 --- a/tests/unittest/conftest.py +++ b/tests/unittest/conftest.py @@ -262,7 +262,7 @@ async def echo_path(scope, receive, send): async def echo_params(scope, receive, send): - body = {"params": parse_qs(scope["query_string"].decode())} + body = {"params": parse_qs(scope["query_string"].decode(), keep_blank_values=True)} await send( { "type": "http.response.start", diff --git a/tests/unittest/test_requests.py b/tests/unittest/test_requests.py index c28fb0e..8a78774 100644 --- a/tests/unittest/test_requests.py +++ b/tests/unittest/test_requests.py @@ -149,6 +149,13 @@ def test_update_params(server): ) assert r.content == b'{"params": {"a": ["1", "2"], "foo": ["z", "1", "2"]}}' + # empty values should be kept + r = requests.get( + str(server.url.copy_with(path="/echo_params?a=")), + params=[("foo", "1"), ("foo", "2")], + ) + assert r.content == b'{"params": {"a": [""], "foo": ["1", "2"]}}' + def test_url_encode(server): # https://github.com/lexiforest/curl_cffi/issues/394 @@ -209,6 +216,11 @@ def test_url_encode(server): r = requests.get(url, quote=False) assert r.url == url + # empty values should be kept + url = "http://127.0.0.1:8000/api?param1=value1¶m2=¶m3=value3" + r = requests.get(url) + assert r.url == url + def test_headers(server): r = requests.get(str(server.url.copy_with(path="/echo_headers")), headers={"foo": "bar"})