diff --git a/httpx/_models.py b/httpx/_models.py index 2cc86321a4..d4e2c4ed66 100644 --- a/httpx/_models.py +++ b/httpx/_models.py @@ -396,7 +396,7 @@ def __init__( extensions: RequestExtensions | None = None, ) -> None: self.method = method.upper() - self.url = URL(url) if params is None else URL(url, params=params) + self.url = URL(url) if params is None else URL(url).copy_merge_params(params) self.headers = Headers(headers) self.extensions = {} if extensions is None else dict(extensions) diff --git a/tests/models/test_requests.py b/tests/models/test_requests.py index b31fe007be..321b611b73 100644 --- a/tests/models/test_requests.py +++ b/tests/models/test_requests.py @@ -232,10 +232,18 @@ def test_request_params(): request = httpx.Request("GET", "http://example.com", params={}) assert str(request.url) == "http://example.com" + # Params are merged with existing URL query parameters, not replaced. request = httpx.Request( "GET", "http://example.com?c=3", params={"a": "1", "b": "2"} ) - assert str(request.url) == "http://example.com?a=1&b=2" + assert str(request.url) == "http://example.com?c=3&a=1&b=2" + # Empty params preserves existing URL query parameters. request = httpx.Request("GET", "http://example.com?a=1", params={}) - assert str(request.url) == "http://example.com" + assert str(request.url) == "http://example.com?a=1" + + # Params with overlapping keys override existing URL query parameters. + request = httpx.Request( + "GET", "http://example.com?a=1&b=2", params={"b": "3", "c": "4"} + ) + assert str(request.url) == "http://example.com?a=1&b=3&c=4"