Fix validation: 0 valid proxies (httpx shared client bug)
httpx.AsyncClient.get() does not accept proxy= per-request. Shared client caused every check_one call to raise TypeError, silently caught as False, so 0/N proxies ever passed. Reverted to per-proxy AsyncClient(proxy=url) in _check_one. Semaphore concurrency + wall-clock cap preserved. Also re-adds _check_one helper that was accidentally removed. Made-with: Cursor
This commit is contained in:
@@ -65,49 +65,33 @@ async def validate_proxies(
|
|||||||
(check_url[:70] + "…") if len(check_url) > 70 else check_url,
|
(check_url[:70] + "…") if len(check_url) > 70 else check_url,
|
||||||
)
|
)
|
||||||
|
|
||||||
t = httpx.Timeout(timeout_seconds, connect=min(8.0, timeout_seconds))
|
|
||||||
lim = max(32, min(256, c * 8))
|
|
||||||
limits = httpx.Limits(max_connections=lim, max_keepalive_connections=max(16, c * 4))
|
|
||||||
|
|
||||||
last_prog_t = 0.0
|
last_prog_t = 0.0
|
||||||
prog_step = max(1, total // 120)
|
prog_step = max(1, total // 120)
|
||||||
|
|
||||||
async def _run_all(client: httpx.AsyncClient) -> None:
|
async def one(u: str) -> None:
|
||||||
nonlocal done, last_prog_t
|
nonlocal done, last_prog_t
|
||||||
|
async with sem:
|
||||||
|
good = await _check_one(u, check_url, timeout_seconds)
|
||||||
|
async with lock:
|
||||||
|
done += 1
|
||||||
|
if good:
|
||||||
|
ok.append(u)
|
||||||
|
if on_progress:
|
||||||
|
now = time.monotonic()
|
||||||
|
if (
|
||||||
|
done == total
|
||||||
|
or done == 1
|
||||||
|
or done % prog_step == 0
|
||||||
|
or (now - last_prog_t) >= 0.1
|
||||||
|
):
|
||||||
|
last_prog_t = now
|
||||||
|
on_progress(done, total)
|
||||||
|
|
||||||
async def one(u: str) -> None:
|
async def _run_all() -> None:
|
||||||
nonlocal done, last_prog_t
|
|
||||||
async with sem:
|
|
||||||
try:
|
|
||||||
r = await client.get(check_url, proxy=u)
|
|
||||||
good = r.status_code == 200 and len(r.content) > 0
|
|
||||||
except Exception:
|
|
||||||
good = False
|
|
||||||
async with lock:
|
|
||||||
done += 1
|
|
||||||
if good:
|
|
||||||
ok.append(u)
|
|
||||||
if on_progress:
|
|
||||||
now = time.monotonic()
|
|
||||||
if (
|
|
||||||
done == total
|
|
||||||
or done == 1
|
|
||||||
or done % prog_step == 0
|
|
||||||
or (now - last_prog_t) >= 0.1
|
|
||||||
):
|
|
||||||
last_prog_t = now
|
|
||||||
on_progress(done, total)
|
|
||||||
|
|
||||||
await asyncio.gather(*(one(u) for u in proxy_urls))
|
await asyncio.gather(*(one(u) for u in proxy_urls))
|
||||||
|
|
||||||
try:
|
try:
|
||||||
async with httpx.AsyncClient(
|
await asyncio.wait_for(_run_all(), timeout=cap)
|
||||||
timeout=t,
|
|
||||||
verify=False,
|
|
||||||
follow_redirects=True,
|
|
||||||
limits=limits,
|
|
||||||
) as client:
|
|
||||||
await asyncio.wait_for(_run_all(client), timeout=cap)
|
|
||||||
except asyncio.TimeoutError:
|
except asyncio.TimeoutError:
|
||||||
log.warning(
|
log.warning(
|
||||||
"validate_proxies wall-clock cap %.0fs exceeded (%d URLs) — returning partial results",
|
"validate_proxies wall-clock cap %.0fs exceeded (%d URLs) — returning partial results",
|
||||||
@@ -118,6 +102,22 @@ async def validate_proxies(
|
|||||||
return ok
|
return ok
|
||||||
|
|
||||||
|
|
||||||
|
async def _check_one(proxy_url: str, check_url: str, timeout_seconds: float) -> bool:
|
||||||
|
"""Check a single proxy by fetching check_url through it. True = live and returns 200."""
|
||||||
|
t = httpx.Timeout(timeout_seconds, connect=min(8.0, timeout_seconds))
|
||||||
|
try:
|
||||||
|
async with httpx.AsyncClient(
|
||||||
|
proxy=proxy_url,
|
||||||
|
timeout=t,
|
||||||
|
verify=False,
|
||||||
|
follow_redirects=True,
|
||||||
|
) as c:
|
||||||
|
r = await c.get(check_url)
|
||||||
|
return r.status_code == 200 and len(r.content) > 0
|
||||||
|
except Exception:
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
async def check_chain_exit_ip(
|
async def check_chain_exit_ip(
|
||||||
listen_proxy: str,
|
listen_proxy: str,
|
||||||
check_url: str,
|
check_url: str,
|
||||||
|
|||||||
Reference in New Issue
Block a user