diff --git a/src/rfc3986/normalizers.py b/src/rfc3986/normalizers.py index 79b3585..7fbcacb 100644 --- a/src/rfc3986/normalizers.py +++ b/src/rfc3986/normalizers.py @@ -43,12 +43,12 @@ def normalize_authority( def normalize_username(username: str) -> str: """Normalize a username to make it safe to include in userinfo.""" - return urlquote(username) + return urlquote(username, safe="") def normalize_password(password: str) -> str: """Normalize a password to make safe for userinfo.""" - return urlquote(password) + return urlquote(password, safe="") def normalize_host(host: str) -> str: diff --git a/tests/test_builder.py b/tests/test_builder.py index eae3ec3..f2c6dd0 100644 --- a/tests/test_builder.py +++ b/tests/test_builder.py @@ -88,6 +88,7 @@ def test_add_scheme(scheme): ("user", None, "user"), ("user@domain.com", "password", "user%40domain.com:password"), ("user", "pass:word", "user:pass%3Aword"), + ("domain/user", "pass/word", "domain%2Fuser:pass%2Fword"), ], ) def test_add_credentials(username, password, userinfo): @@ -102,6 +103,26 @@ def test_add_credentials_requires_username(): builder.URIBuilder().add_credentials(None, None) +@pytest.mark.parametrize( + "username, password", + [("domain/user", "password"), ("user", "pass/word")], +) +def test_credentials_with_slashes_preserve_uri_components(username, password): + """Keep credential slashes from terminating the URI authority.""" + reference = ( + builder.URIBuilder() + .add_scheme("https") + .add_host("example.com") + .add_credentials(username, password) + .add_path("resource") + .finalize() + ) + reparsed = uri_reference(reference.unsplit()) + assert reparsed.host == "example.com" + assert reparsed.userinfo == reference.userinfo + assert reparsed.path == "/resource" + + @pytest.mark.parametrize( ["hostname", "expected_hostname"], [