Prefer browser PKCE mint over flaky direct HTTP to auth.x.ai.

Logs show curl(28)/ReadTimeout on direct mint while registration browser
still works; skip slow requests fallback, shorten HTTP step timeout, and
mint via page first when available.
This commit is contained in:
chaos committed 2026-07-14 10:19:25 +08:00
1 parent 8b399277e7
commit 96061cbd78
3 files changed
+68 -55

No files matched your search

+20 -31
View File
@@ -260,6 +260,10 @@ def _final_url(resp: Any) -> str:
return ""
# HTTP 铸造单步超时:直连/跨境链路差时不要卡 30s,尽快让上层走浏览器
HTTP_STEP_TIMEOUT = 12
def open_authorize_page(session: Any, flow: AuthCodeFlow) -> str:
params = {
"response_type": "code",
@@ -277,7 +281,7 @@ def open_authorize_page(session: Any, flow: AuthCodeFlow) -> str:
url,
headers=_browser_headers("GET", url),
allow_redirects=True,
timeout=30,
timeout=HTTP_STEP_TIMEOUT,
)
body = resp.text or ""
final = _final_url(resp)
@@ -355,7 +359,7 @@ def approve_authorization(session: Any, consent_url: str, flow: AuthCodeFlow) ->
data=body.encode("utf-8"),
headers=_browser_headers("POST", consent_url, NEXT_ACTION_ID),
allow_redirects=True,
timeout=30,
timeout=HTTP_STEP_TIMEOUT,
)
text = resp.text or ""
if resp.status_code < 200 or resp.status_code >= 300:
@@ -384,7 +388,7 @@ def exchange_auth_code(session: Any, code: str, flow: AuthCodeFlow) -> TokenResu
TOKEN_URL,
data=urlencode(form),
headers=_token_headers(),
timeout=30,
timeout=HTTP_STEP_TIMEOUT,
)
text = resp.text or ""
if resp.status_code < 200 or resp.status_code >= 300:
@@ -454,47 +458,27 @@ def sso_to_token(
log: LogFn | None = None,
require_referrer: bool = True,
) -> TokenResult:
"""SSO cookie → 带 referrer=grok-build 的 OAuth token。"""
"""SSO cookie → 带 referrer=grok-build 的 OAuth token。
仅用 curl_cffi(Chrome TLS)。不再回退 std requests:
实测 requests 访问 auth.x.ai / accounts.x.ai 常 ReadTimeout,比 curl 更差。
连接/TLS/超时由上层切到浏览器 PKCE。
"""
log = log or _noop_log
sso = normalize_sso_cookie(sso_cookie)
if not sso:
raise OAuthCodeError("sso cookie 为空")
# 先 curl_cffi;若遇到 OpenSSL invalid library / curl(35),自动回退 std requests
session = _make_session(proxy, prefer="curl")
try:
return _run_sso_flow(
sso, session=session, log=log, require_referrer=require_referrer
)
except Exception as exc: # noqa: BLE001
backend = str(getattr(session, "_cpa_http_backend", "") or "")
can_fallback = _is_curl_tls_broken(exc) or (
backend.startswith("curl_cffi") and "curl: (35)" in str(exc).lower()
)
if not can_fallback:
raise
log(f"curl TLS 异常,回退标准 requests: {_short(str(exc), 160)}")
finally:
try:
session.close()
except Exception:
pass
session = _make_session(proxy, prefer="requests")
try:
return _run_sso_flow(
sso, session=session, log=log, require_referrer=require_referrer
)
finally:
try:
session.close()
except Exception:
pass
session = None # type: ignore[assignment]
finally:
if session is not None:
try:
session.close()
except Exception:
pass
def mint_from_sso(
@@ -523,7 +507,7 @@ def mint_from_sso(
def _is_http_tls_failure(exc: BaseException | str) -> bool:
"""HTTP 层 TLS/连接失败:适合改走浏览器铸造。"""
"""HTTP 层 TLS/连接/超时失败:适合改走浏览器铸造。"""
text = str(exc or "").lower()
needles = (
"unexpected_eof_while_reading",
@@ -533,11 +517,16 @@ def _is_http_tls_failure(exc: BaseException | str) -> bool:
"openssl_internal:invalid library",
"tls connect error",
"curl: (35)",
"curl: (28)",
"failed to perform, curl: (35)",
"failed to perform, curl: (28)",
"connection timed out",
"ssl_error_syscall",
"connection reset",
"connection aborted",
"name resolution",
"readtimeout",
"connecttimeout",
"timed out",
"timeout",
)