Merge pull request #808 from christianlouis/fix/double-slashes-join-url-12822045781097996485

Fix double slashes again
This commit is contained in:
Christian Krakau-Louis
2026-03-23 17:27:08 +01:00
committed by GitHub
4 changed files with 241 additions and 157 deletions
+26
View File
@@ -1,6 +1,7 @@
import ipaddress
import logging
import socket
from urllib.parse import urlsplit, urlunsplit
logger = logging.getLogger(__name__)
@@ -32,3 +33,28 @@ def is_private_ip(hostname: str) -> bool:
# and SSRF bypasses via unresolvable addresses.
logger.warning(f"Could not resolve hostname (blocking securely): {hostname}")
return True
def join_url(base: str, *parts: str) -> str:
"""
Safely join a base URL with one or more path parts.
Uses urllib.parse to correctly handle scheme/netloc/query/fragment so that
only the path component is modified. Leading and trailing slashes are
stripped from each part before joining, preventing double-slash sequences
at segment boundaries without touching the scheme separator or query string.
Examples:
join_url("https://example.com/dav/", "/remote/", "file.pdf")
-> "https://example.com/dav/remote/file.pdf"
"""
parsed = urlsplit(base)
# Strip each part once and filter out empty segments; use walrus operator
# to avoid calling strip twice per iteration.
stripped_parts = [s for p in parts if (s := p.strip("/"))]
base_path = parsed.path.rstrip("/")
new_path = base_path + "/" + "/".join(stripped_parts) if stripped_parts else base_path
# Ensure path is non-empty so the reconstructed URL is valid.
if not new_path:
new_path = "/"
return urlunsplit((parsed.scheme, parsed.netloc, new_path, parsed.query, parsed.fragment))