perf: parallelize captive portal checks with asyncio.gather

Co-authored-by: Horizontal42 <75383519+Horizontal42@users.noreply.github.com>
This commit is contained in:
google-labs-jules[bot] 2026-09-10 08:43:48 +00:00
parent 8c99ac78b7
commit 4231a440df

View file

@ -1,5 +1,6 @@
from __future__ import annotations
import asyncio
from urllib.parse import urlsplit
import httpx
@ -28,7 +29,10 @@ def classify_portal_response(
if redirect_host and redirect_host != requested_host:
return "portal", f"redirected to a different host ({redirect_host})"
if status == 200 and body:
return "portal", f"200 with a non-empty body instead of the expected {expected_status}"
return (
"portal",
f"200 with a non-empty body instead of the expected {expected_status}",
)
return "suspect", f"unexpected status {status}"
@ -39,18 +43,23 @@ async def check_captive_portal(
expected_status: int = 204,
timeout: float,
) -> CaptivePortal:
checks: list[PortalCheck] = []
for url in urls:
async def _check_url(url: str) -> PortalCheck:
try:
response = await client.get(url, follow_redirects=False, timeout=timeout)
verdict, evidence = classify_portal_response(
url, response.status_code, response.text, response.headers.get("location"), expected_status
url,
response.status_code,
response.text,
response.headers.get("location"),
expected_status,
)
return PortalCheck(
url=url, status=response.status_code, verdict=verdict, evidence=evidence
)
except httpx.HTTPError as exc:
verdict, evidence = "error", str(exc)
checks.append(PortalCheck(url=url, status=None, verdict=verdict, evidence=evidence))
continue
checks.append(PortalCheck(url=url, status=response.status_code, verdict=verdict, evidence=evidence))
return PortalCheck(url=url, status=None, verdict="error", evidence=str(exc))
checks: list[PortalCheck] = await asyncio.gather(*(_check_url(url) for url in urls))
portal_checks = [c for c in checks if c.verdict == "portal"]
if portal_checks: