Skip to content

Commit

Permalink
Improve InvalidURL error message. (#3250)
Browse files Browse the repository at this point in the history
  • Loading branch information
tomchristie committed Jul 26, 2024
1 parent beb501f commit 7c0cda1
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 7 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
17 changes: 14 additions & 3 deletions httpx/_urlparse.py
Original file line number Diff line number Diff line change
Expand Up @@ -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.
# ------------------------------------------------
Expand Down Expand Up @@ -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):
Expand Down
10 changes: 6 additions & 4 deletions tests/models/test_url.py
Original file line number Diff line number Diff line change
Expand Up @@ -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."
)


Expand Down

0 comments on commit 7c0cda1

Please sign in to comment.