This commit is contained in:
Andrew Pimenov 2026-08-26 17:03:46 +03:00 • committed by GitHub
commit bd1192e0a7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -1,5 +1,6 @@
from __future__ import annotations from __future__ import annotations
import asyncio
from urllib.parse import urlsplit from urllib.parse import urlsplit
import httpx import httpx
@ -32,6 +33,23 @@ def classify_portal_response(
return "suspect", f"unexpected status {status}" return "suspect", f"unexpected status {status}"
async def _fetch_and_classify(
client: httpx.AsyncClient,
url: str,
expected_status: int,
timeout: float,
) -> 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
)
return PortalCheck(url=url, status=response.status_code, verdict=verdict, evidence=evidence)
except httpx.HTTPError as exc:
verdict, evidence = "error", str(exc)
return PortalCheck(url=url, status=None, verdict=verdict, evidence=evidence)
async def check_captive_portal( async def check_captive_portal(
client: httpx.AsyncClient, client: httpx.AsyncClient,
urls: list[str], urls: list[str],
@ -39,18 +57,11 @@ async def check_captive_portal(
expected_status: int = 204, expected_status: int = 204,
timeout: float, timeout: float,
) -> CaptivePortal: ) -> CaptivePortal:
checks: list[PortalCheck] = [] coros = [
for url in urls: _fetch_and_classify(client, url, expected_status, timeout)
try: for url in urls
response = await client.get(url, follow_redirects=False, timeout=timeout) ]
verdict, evidence = classify_portal_response( checks = list(await asyncio.gather(*coros))
url, response.status_code, response.text, response.headers.get("location"), expected_status
)
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))
portal_checks = [c for c in checks if c.verdict == "portal"] portal_checks = [c for c in checks if c.verdict == "portal"]
if portal_checks: if portal_checks: