Detect Cloudflare 403 on mint and retry alternate proxies.
- Clear CF block errors with egress label and config hint - Log mint exit (direct/proxy); probe local proxy ports on 403 - Retry mint_proxy/proxy/pool candidates without browser mint
This commit is contained in:
1 parent
cc0aa6a433
commit
7d6d52ac5d
2 files changed
+186
-17
No files matched your search
@@ -138,6 +138,39 @@ def _is_curl_tls_broken(exc: BaseException | str) -> bool:
|
||||
return any(n in text for n in needles)
|
||||
|
||||
|
||||
def is_cloudflare_block(
|
||||
status: int | None = None,
|
||||
body: str = "",
|
||||
exc: BaseException | str | None = None,
|
||||
) -> bool:
|
||||
"""识别 auth.x.ai 被 Cloudflare 拦(常见直连 403 挑战页)。"""
|
||||
text = f"{body or ''} {exc or ''}".lower()
|
||||
if status == 403 and (
|
||||
"<!doctype html" in text
|
||||
or "cloudflare" in text
|
||||
or "cf-ray" in text
|
||||
or "attention required" in text
|
||||
or "just a moment" in text
|
||||
or "enable javascript" in text
|
||||
or "oldie" in text
|
||||
):
|
||||
return True
|
||||
if "authorize http 403" in text and (
|
||||
"<!doctype" in text or "oldie" in text or "cloudflare" in text
|
||||
):
|
||||
return True
|
||||
return "cloudflare" in text and ("403" in text or "blocked" in text)
|
||||
|
||||
|
||||
def _cf_block_hint(proxy_label: str = "") -> str:
|
||||
via = proxy_label or "(direct)"
|
||||
return (
|
||||
f"Cloudflare 拦截 auth.x.ai(出口={via})。"
|
||||
"直连大陆/机房 IP 几乎必 403;请配置 mint_proxy / proxy,"
|
||||
"或开启 proxy_pool_enabled 并保证代理能访问 auth.x.ai。"
|
||||
)
|
||||
|
||||
|
||||
def _make_std_session(proxy: str | None = None):
|
||||
try:
|
||||
import requests as std_requests
|
||||
@@ -300,6 +333,10 @@ def open_authorize_page(session: Any, flow: AuthCodeFlow) -> str:
|
||||
body = resp.text or ""
|
||||
final = _final_url(resp)
|
||||
if resp.status_code < 200 or resp.status_code >= 300:
|
||||
if is_cloudflare_block(resp.status_code, body):
|
||||
raise OAuthCodeError(
|
||||
f"authorize HTTP {resp.status_code}: Cloudflare 拦截 — {_short(body, 80)}"
|
||||
)
|
||||
raise OAuthCodeError(
|
||||
f"authorize HTTP {resp.status_code}: {_short(body)}"
|
||||
)
|
||||
@@ -478,11 +515,16 @@ def sso_to_token(
|
||||
require_referrer: bool = True,
|
||||
) -> TokenResult:
|
||||
"""SSO cookie → 带 referrer=grok-build 的 OAuth token。"""
|
||||
from .proxyutil import proxy_log_label, resolve_proxy
|
||||
|
||||
log = log or _noop_log
|
||||
sso = normalize_sso_cookie(sso_cookie)
|
||||
if not sso:
|
||||
raise OAuthCodeError("sso cookie 为空")
|
||||
|
||||
resolved = resolve_proxy(proxy)
|
||||
log(f"mint 出口={proxy_log_label(resolved) or '(direct)'}")
|
||||
|
||||
# 先 curl_cffi;若遇到 OpenSSL invalid library / curl(35),自动回退 std requests
|
||||
session = _make_session(proxy, prefer="curl")
|
||||
try:
|
||||
@@ -495,6 +537,8 @@ def sso_to_token(
|
||||
backend.startswith("curl_cffi") and "curl: (35)" in str(exc).lower()
|
||||
)
|
||||
if not can_fallback:
|
||||
if is_cloudflare_block(exc=exc):
|
||||
raise OAuthCodeError(_cf_block_hint(proxy_log_label(resolved))) from exc
|
||||
raise
|
||||
log(f"curl TLS 异常,回退标准 requests: {_short(str(exc), 160)}")
|
||||
try:
|
||||
@@ -506,6 +550,10 @@ def sso_to_token(
|
||||
return _run_sso_flow(
|
||||
sso, session=session, log=log, require_referrer=require_referrer
|
||||
)
|
||||
except Exception as exc2: # noqa: BLE001
|
||||
if is_cloudflare_block(exc=exc2):
|
||||
raise OAuthCodeError(_cf_block_hint(proxy_log_label(resolved))) from exc2
|
||||
raise
|
||||
finally:
|
||||
try:
|
||||
session.close()
|
||||
|
||||
Reference in new issue
Block a user