diff --git a/src/hyperlink/_url.py b/src/hyperlink/_url.py index 8797b5c..d6e507e 100644 --- a/src/hyperlink/_url.py +++ b/src/hyperlink/_url.py @@ -1619,6 +1619,12 @@ def click(self, href=u""): else: clicked = self + if clicked.uses_netloc: + return clicked.replace( + scheme=clicked.scheme or self.scheme, + path=_resolve_dot_segments(clicked.path), + ) + query = clicked.query if clicked.scheme and not clicked.rooted: # Schemes with relative paths are not well-defined. RFC 3986 calls diff --git a/src/hyperlink/test/test_url.py b/src/hyperlink/test/test_url.py index 37c9172..de0c23e 100644 --- a/src/hyperlink/test/test_url.py +++ b/src/hyperlink/test/test_url.py @@ -412,6 +412,29 @@ def test_sibling(self): urlpath.sibling("sister").to_text(), ) + def test_click_network_path_replaces_authority(self): + # type: () -> None + base = URL.from_text("http://user:password@example.com:8080/old?q=base") + for href, expected in [ + ("//other.example/new", "http://other.example/new"), + ("//other.example", "http://other.example"), + ("//other.example?x=1", "http://other.example/?x=1"), + ("//other.example:0/new", "http://other.example:0/new"), + ("//newuser@other.example/new", "http://newuser@other.example/new"), + ("//other.example/a/../new", "http://other.example/new"), + ]: + self.assertEqual( + base.click(href).to_text(with_password=True), expected + ) + self.assertEqual( + base.click("/new").to_text(with_password=True), + "http://user:password@example.com:8080/new", + ) + self.assertEqual( + base.to_text(with_password=True), + "http://user:password@example.com:8080/old?q=base", + ) + def test_click(self): # type: () -> None """