From 1ff9a635bd9b033b631a6b525891b7eb44e189d3 Mon Sep 17 00:00:00 2001 From: historia Date: Mon, 24 Aug 2026 16:08:33 -0400 Subject: feat: clearer split between local (managed) and remote URLs and server status --- app/backends/common.py | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) (limited to 'app/backends/common.py') diff --git a/app/backends/common.py b/app/backends/common.py index 42faa7e..d5e1b6b 100644 --- a/app/backends/common.py +++ b/app/backends/common.py @@ -150,6 +150,38 @@ def url_with_port(url: str, port: int) -> str: (parts.scheme or "http", f"{host}:{port}", parts.path, "", "")) +def normalize_remote_url(value: str) -> str: + """Normalize a user-supplied remote server URL, or '' for "disabled". + + Accepts a bare ``host[:port]`` (a scheme of ``http`` is assumed), a full + ``http(s)://host[:port][/path]`` URL, or the empty string (no remote + server configured). Returns the normalized URL (bare host:port becomes + ``http://host:port``). Raises ValueError for anything else — a missing + host, a host containing whitespace, or a non-numeric port. + """ + cleaned = value.strip() + if not cleaned: + return "" + parts = urllib.parse.urlsplit(cleaned) + if not parts.scheme: + # Bare host[:port] — add the default scheme so netloc/host/port + # parse cleanly. An explicit scheme is kept as-is (so "http://" + # with no host fails the host check below). + parts = urllib.parse.urlsplit(f"http://{cleaned}") + host = parts.hostname + if not host or any(ch.isspace() for ch in host): + raise ValueError( + "Enter a host:port (e.g. 10.20.30.40:8000) or a full URL " + f"(e.g. http://10.20.30.40:8000); got {value!r}") + try: + parts.port # raises ValueError for a non-numeric port + except ValueError as exc: + raise ValueError( + f"Invalid port in remote URL {value!r}: {exc}") from exc + return urllib.parse.urlunsplit( + (parts.scheme or "http", parts.netloc, parts.path, "", "")) + + def server_running(url: str, timeout: float = 0.3) -> bool: """True when something accepts TCP connections at URL's host:port. -- cgit v1.2.3