From 90ef2daef1b59c8bdf04e5ada9aa371ce2bc64e9 Mon Sep 17 00:00:00 2001 From: tboy1337 Date: Sun, 26 Oct 2025 00:22:24 +0100 Subject: [PATCH] Enhance HTTPDigestAuth to include semicolons in the URI path. Added a test to verify correct handling of URLs with semicolons, addressing issue #6990. --- src/requests/auth.py | 2 ++ tests/test_requests.py | 39 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+) diff --git a/src/requests/auth.py b/src/requests/auth.py index 4a7ce6dc14..2557bc8fda 100644 --- a/src/requests/auth.py +++ b/src/requests/auth.py @@ -183,6 +183,8 @@ def sha512_utf8(x): p_parsed = urlparse(url) #: path is request-uri defined in RFC 2616 which should not be empty path = p_parsed.path or "/" + if p_parsed.params: + path += f";{p_parsed.params}" if p_parsed.query: path += f"?{p_parsed.query}" diff --git a/tests/test_requests.py b/tests/test_requests.py index 75d2deff2e..636cecec11 100644 --- a/tests/test_requests.py +++ b/tests/test_requests.py @@ -805,6 +805,45 @@ def test_DIGESTAUTH_QUOTES_QOP_VALUE(self, httpbin): r = requests.get(url, auth=auth) assert '"auth"' in r.request.headers["Authorization"] + def test_DIGESTAUTH_WITH_SEMICOLONS_IN_PATH(self): + """Test that digest auth correctly includes semicolons in the uri field. + + This tests issue #6990 where semicolons in URL paths were being + truncated in the digest auth uri field. + """ + from unittest.mock import Mock, patch + + auth = HTTPDigestAuth("user", "pass") + + # Initialize the auth state + auth.init_per_thread_state() + auth._thread_local.chal = { + "realm": "test-realm", + "nonce": "test-nonce", + "qop": "auth", + "algorithm": "MD5" + } + auth._thread_local.last_nonce = "" + + # Test URL with semicolons in the path (MusicBrainz-style API) + test_url = "https://example.com/api/collection/id1/releases/uuid1;uuid2;uuid3?fmt=json&client=test" + + # Build the digest header + header = auth.build_digest_header("PUT", test_url) + + # Extract the uri field from the Authorization header + assert 'uri="/api/collection/id1/releases/uuid1;uuid2;uuid3?fmt=json&client=test"' in header + + # Test with semicolons but no query parameters + test_url2 = "https://example.com/path/id1;id2;id3" + header2 = auth.build_digest_header("GET", test_url2) + assert 'uri="/path/id1;id2;id3"' in header2 + + # Test with just path (no semicolons or query) + test_url3 = "https://example.com/simple/path" + header3 = auth.build_digest_header("GET", test_url3) + assert 'uri="/simple/path"' in header3 + def test_POSTBIN_GET_POST_FILES(self, httpbin): url = httpbin("post") requests.post(url).raise_for_status()