From 989717e47921ba0f9c57a31ed1fedcc30fe22d9d Mon Sep 17 00:00:00 2001 From: Malin Date: Mon, 20 Apr 2026 19:50:56 +0200 Subject: [PATCH] fix: always retry https on any http failure, unify timeouts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Any http failure (ConnectError, ConnectTimeout, ReadTimeout, TLS error inside a redirect chain) now falls through to an https retry instead of immediately marking dead. - Use one unified 8s connect / 12s read timeout for both schemes so that http→https redirects followed inside the same client get a full TLS handshake window (previously 4s http timeout was too short for the https redirect hop). Co-Authored-By: Claude Sonnet 4.6 --- app/validator.py | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/app/validator.py b/app/validator.py index 7374a7d..46cecfa 100644 --- a/app/validator.py +++ b/app/validator.py @@ -108,15 +108,14 @@ async def _check_domain(domain: str) -> dict: # will too, so we don't bother retrying on timeout errors. # We DO retry https on ConnectError/RemoteProtocolError (port 80 closed or # speaking wrong protocol) because those servers are often https-only. - timeouts = { - "http": httpx.Timeout(connect=4, read=6, write=3, pool=5), - "https": httpx.Timeout(connect=6, read=10, write=3, pool=5), - } + # Use the same generous timeout for both schemes so that http→https redirects + # (followed inside the same client) also get enough time for the TLS handshake. + timeout = httpx.Timeout(connect=8, read=12, write=5, pool=8) for scheme in ("http", "https"): try: async with httpx.AsyncClient( - timeout=timeouts[scheme], + timeout=timeout, follow_redirects=True, headers=_headers(), verify=False, @@ -152,16 +151,14 @@ async def _check_domain(domain: str) -> dict: result["prescreen_status"] = "live" return result - except (httpx.ConnectError, httpx.RemoteProtocolError, httpx.ConnectTimeout) as e: - # Port refused, wrong protocol, or port 80 firewalled/timed-out - # → server may be https-only, always retry on 443 + except Exception as e: + # Any failure on http (connection refused, timeout, TLS error in redirect + # chain, etc.) → server may be https-only, always try 443 once. if scheme == "http": logger.debug("Validator %s: %s on http, trying https", domain, type(e).__name__) continue - break - except Exception as e: - # ReadTimeout or other error — connected but server too slow; mark dead - logger.debug("Validator %s (%s): %s", domain, scheme, type(e).__name__) + # Both schemes failed → dead + logger.debug("Validator %s (https): %s", domain, type(e).__name__) break result["load_time_ms"] = int((time.monotonic() - t0) * 1000)