diff options
Diffstat (limited to '')
| -rw-r--r-- | webmentions_ssg/url_security.py | 28 |
1 files changed, 15 insertions, 13 deletions
diff --git a/webmentions_ssg/url_security.py b/webmentions_ssg/url_security.py index ce5d700..51c037a 100644 --- a/webmentions_ssg/url_security.py +++ b/webmentions_ssg/url_security.py @@ -9,15 +9,11 @@ class AddressResolutionError(Exception): pass -class NonPublicAddressError(Exception): - pass - - -def ensure_public_url(url: str) -> None: +def is_public_url(url: str) -> bool: hostname = urlsplit(url).hostname if hostname is None: - raise NonPublicAddressError("URL has no hostname") + raise ValueError("No hostname was specified") try: answers = dns.resolver.resolve_name(hostname) @@ -25,13 +21,19 @@ def ensure_public_url(url: str) -> None: raise AddressResolutionError( f"Could not resolve hostname {hostname!r}" ) from exc + else: + for address in answers.addresses(): + if not ipaddress.ip_address(address).is_global: + return False - addresses = {ipaddress.ip_address(address) for address in answers.addresses()} + return True - if not addresses: - raise AddressResolutionError(f"Hostname {hostname!r} did not resolve") - if any(not address.is_global for address in addresses): - raise NonPublicAddressError( - f"Hostname {hostname!r} resolves to a non-public address" - ) +def is_http_url(url: str) -> bool: + """Return whether a URL is an absolute HTTP or HTTPS URL.""" + try: + parsed = urlsplit(url) + except ValueError: + return False + + return parsed.scheme.lower() in {"http", "https"} and parsed.hostname is not None |
