]> git.ipfire.org Git - thirdparty/httpx.git/commitdiff
Handle URL quoting username and password components. (#1159)
authorTom Christie <tom@tomchristie.com>
Tue, 11 Aug 2020 16:18:12 +0000 (17:18 +0100)
committerGitHub <noreply@github.com>
Tue, 11 Aug 2020 16:18:12 +0000 (17:18 +0100)
* Handle URL quoting username and password components

* Tweak userinfo quoting

httpx/_models.py
tests/models/test_url.py

index 8d294e7f237944e3578e08d32d1546bb98bb0691..d6bc46e16343757335ec3b0eeea95a6878e6bf96 100644 (file)
@@ -7,7 +7,7 @@ import urllib.request
 import warnings
 from collections.abc import MutableMapping
 from http.cookiejar import Cookie, CookieJar
-from urllib.parse import parse_qsl, urlencode
+from urllib.parse import parse_qsl, quote, unquote, urlencode
 
 import chardet
 import rfc3986
@@ -100,12 +100,12 @@ class URL:
     @property
     def username(self) -> str:
         userinfo = self._uri_reference.userinfo or ""
-        return userinfo.partition(":")[0]
+        return unquote(userinfo.partition(":")[0])
 
     @property
     def password(self) -> str:
         userinfo = self._uri_reference.userinfo or ""
-        return userinfo.partition(":")[2]
+        return unquote(userinfo.partition(":")[2])
 
     @property
     def host(self) -> str:
@@ -175,8 +175,8 @@ class URL:
         ):
             host = kwargs.pop("host", self.host)
             port = kwargs.pop("port", self.port)
-            username = kwargs.pop("username", self.username)
-            password = kwargs.pop("password", self.password)
+            username = quote(kwargs.pop("username", self.username) or "")
+            password = quote(kwargs.pop("password", self.password) or "")
 
             authority = host
             if port is not None:
@@ -193,7 +193,7 @@ class URL:
 
     def join(self, url: URLTypes) -> "URL":
         """
-        Return an absolute URL, using given this URL as the base.
+        Return an absolute URL, using this URL as the base.
         """
         if self.is_relative_url:
             return URL(url)
index 19e07575d39172551cf341f8830c043b5625f327..c4975a92e97909a6a2db40e4a7d8f4f7d835af47 100644 (file)
@@ -187,6 +187,18 @@ def test_url_copywith_for_authority():
     assert str(new) == "https://username:password@example.net:444"
 
 
+def test_url_copywith_for_userinfo():
+    copy_with_kwargs = {
+        "username": "tom@example.org",
+        "password": "abc123@ %",
+    }
+    url = URL("https://example.org")
+    new = url.copy_with(**copy_with_kwargs)
+    assert str(new) == "https://tom%40example.org:abc123%40%20%25@example.org"
+    assert new.username == "tom@example.org"
+    assert new.password == "abc123@ %"
+
+
 def test_url_invalid():
     with pytest.raises(InvalidURL):
         URL("https://😇/")