Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix URL.build not validating that path has a leading slash when passing authority #1265

Merged
merged 3 commits into from
Oct 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGES/1265.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Fixed :py:meth:`~yarl.URL.build` failing to validate paths must start with a ``/`` when passing ``authority`` -- by :user:`bdraco`.

The validation only worked correctly when passing ``host``.
8 changes: 7 additions & 1 deletion tests/test_url_build.py
Original file line number Diff line number Diff line change
Expand Up @@ -140,12 +140,18 @@ def test_build_with_invalid_host(host: str, is_authority: bool):


def test_build_with_authority():
url = URL.build(scheme="http", authority="степан:[email protected]:8000", path="path")
url = URL.build(scheme="http", authority="степан:[email protected]:8000", path="/path")
assert (
str(url) == "http://%D1%81%D1%82%D0%B5%D0%BF%D0%B0%D0%BD:[email protected]:8000/path"
)


def test_build_with_authority_no_leading_flash():
msg = r"Path in a URL with authority should start with a slash \('/'\) if set"
with pytest.raises(ValueError, match=msg):
URL.build(scheme="http", authority="степан:[email protected]:8000", path="path")


def test_build_with_authority_without_encoding():
url = URL.build(
scheme="http", authority="foo:[email protected]:8000", path="path", encoded=True
Expand Down
19 changes: 8 additions & 11 deletions yarl/_url.py
Original file line number Diff line number Diff line change
Expand Up @@ -309,7 +309,8 @@ def __new__(
if netloc:
if "." in path:
path = cls._normalize_path(path)
cls._validate_authority_uri_abs_path(host, path)
if path[0] != "/":
cls._raise_for_authority_missing_abs_path()

query = cls._QUERY_REQUOTER(query) if query else query
fragment = cls._FRAGMENT_REQUOTER(fragment) if fragment else fragment
Expand Down Expand Up @@ -407,7 +408,8 @@ def build(
if path and netloc:
if "." in path:
path = cls._normalize_path(path)
cls._validate_authority_uri_abs_path(host, path)
if path[0] != "/":
cls._raise_for_authority_missing_abs_path()

query_string = (
cls._QUERY_QUOTER(query_string) if query_string else query_string
Expand Down Expand Up @@ -947,15 +949,10 @@ def suffixes(self) -> tuple[str, ...]:
return tuple(self._UNQUOTER(suffix) for suffix in self.raw_suffixes)

@staticmethod
def _validate_authority_uri_abs_path(host: str, path: str) -> None:
"""Ensure that path in URL with authority starts with a leading slash.

Raise ValueError if not.
"""
if host and path and path[0] != "/":
raise ValueError(
"Path in a URL with authority should start with a slash ('/') if set"
)
def _raise_for_authority_missing_abs_path() -> None:
"""Raise when he path in URL with authority starts lacks a leading slash."""
msg = "Path in a URL with authority should start with a slash ('/') if set"
raise ValueError(msg)

def _make_child(self, paths: "Sequence[str]", encoded: bool = False) -> "URL":
"""
Expand Down