]> git.ipfire.org Git - thirdparty/httpx.git/commitdiff
Improve InvalidURL error message. (#3250)
authorTom Christie <tom@tomchristie.com>
Fri, 26 Jul 2024 08:36:03 +0000 (09:36 +0100)
committerGitHub <noreply@github.com>
Fri, 26 Jul 2024 08:36:03 +0000 (09:36 +0100)
CHANGELOG.md
httpx/_urlparse.py
tests/models/test_url.py

index 18ded9d27f17ba1669356288b41f692580a495a7..d8c2ec7ccbfb67a3fea33f451fd5021560dbbf29 100644 (file)
@@ -12,6 +12,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
 
 ### Fixed
 
+* Improved error messaging for `InvalidURL` exceptions. (#3250)
 * Fix `app` type signature in `ASGITransport`. (#3109)
 
 ## 0.27.0 (21st February, 2024)
index 215c5368f6a358c61101ef3e015eb8d473ce91d1..479c2ef8a1da18df9f112222ecb14f78edf73ff2 100644 (file)
@@ -160,7 +160,12 @@ def urlparse(url: str = "", **kwargs: str | None) -> ParseResult:
     # If a URL includes any ASCII control characters including \t, \r, \n,
     # then treat it as invalid.
     if any(char.isascii() and not char.isprintable() for char in url):
-        raise InvalidURL("Invalid non-printable ASCII character in URL")
+        char = next(char for char in url if char.isascii() and not char.isprintable())
+        idx = url.find(char)
+        error = (
+            f"Invalid non-printable ASCII character in URL, {char!r} at position {idx}."
+        )
+        raise InvalidURL(error)
 
     # Some keyword arguments require special handling.
     # ------------------------------------------------
@@ -205,9 +210,15 @@ def urlparse(url: str = "", **kwargs: str | None) -> ParseResult:
             # If a component includes any ASCII control characters including \t, \r, \n,
             # then treat it as invalid.
             if any(char.isascii() and not char.isprintable() for char in value):
-                raise InvalidURL(
-                    f"Invalid non-printable ASCII character in URL component '{key}'"
+                char = next(
+                    char for char in value if char.isascii() and not char.isprintable()
+                )
+                idx = value.find(char)
+                error = (
+                    f"Invalid non-printable ASCII character in URL {key} component, "
+                    f"{char!r} at position {idx}."
                 )
+                raise InvalidURL(error)
 
             # Ensure that keyword arguments match as a valid regex.
             if not COMPONENT_REGEX[key].fullmatch(value):
index 48872be89fefce1517ca3d89ed6e447835f0167d..523a89bf6501931e4c41bba77763299dfc44415a 100644 (file)
@@ -367,15 +367,17 @@ def test_url_excessively_long_component():
 def test_url_non_printing_character_in_url():
     with pytest.raises(httpx.InvalidURL) as exc:
         httpx.URL("https://www.example.com/\n")
-    assert str(exc.value) == "Invalid non-printable ASCII character in URL"
+    assert str(exc.value) == (
+        "Invalid non-printable ASCII character in URL, '\\n' at position 24."
+    )
 
 
 def test_url_non_printing_character_in_component():
     with pytest.raises(httpx.InvalidURL) as exc:
         httpx.URL("https://www.example.com", path="/\n")
-    assert (
-        str(exc.value)
-        == "Invalid non-printable ASCII character in URL component 'path'"
+    assert str(exc.value) == (
+        "Invalid non-printable ASCII character in URL path component, "
+        "'\\n' at position 1."
     )