mirror of
https://github.com/fawney19/Aether.git
synced 2026-09-02 01:10:23 +08:00
feat: OAuth HTTP 请求添加重试机制和增强错误日志
- 新增 _redact_url 函数移除 URL 敏感参数 - 新增 _format_exc_chain 函数格式化异常链 - _httpx_post 对 ConnectError/TimeoutException 增加重试(最多 2 次) - 增强日志输出:记录代理配置、主机、异常链等调试信息
This commit is contained in:
@@ -2,6 +2,7 @@ from __future__ import annotations
|
|||||||
|
|
||||||
import asyncio
|
import asyncio
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
from urllib.parse import urlsplit, urlunsplit
|
||||||
|
|
||||||
import httpx
|
import httpx
|
||||||
import jwt
|
import jwt
|
||||||
@@ -25,6 +26,25 @@ def _coerce_proxy_url(proxy_config: dict[str, Any] | None) -> str | None:
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def _redact_url(url: str) -> str:
|
||||||
|
"""Remove query and fragment to avoid leaking secrets in logs."""
|
||||||
|
try:
|
||||||
|
parts = urlsplit(url)
|
||||||
|
return urlunsplit((parts.scheme, parts.netloc, parts.path, "", ""))
|
||||||
|
except Exception:
|
||||||
|
return "<invalid_url>"
|
||||||
|
|
||||||
|
|
||||||
|
def _format_exc_chain(e: BaseException) -> str:
|
||||||
|
parts: list[str] = []
|
||||||
|
cur: BaseException | None = e
|
||||||
|
while cur is not None:
|
||||||
|
parts.append(f"{type(cur).__name__}: {cur}")
|
||||||
|
nxt = getattr(cur, "__cause__", None) or getattr(cur, "__context__", None)
|
||||||
|
cur = nxt if isinstance(nxt, BaseException) else None
|
||||||
|
return " <- ".join(parts)
|
||||||
|
|
||||||
|
|
||||||
async def _httpx_post(
|
async def _httpx_post(
|
||||||
url: str,
|
url: str,
|
||||||
*,
|
*,
|
||||||
@@ -35,13 +55,67 @@ async def _httpx_post(
|
|||||||
timeout_seconds: float,
|
timeout_seconds: float,
|
||||||
) -> httpx.Response:
|
) -> httpx.Response:
|
||||||
client = await HTTPClientPool.get_proxy_client(proxy_config)
|
client = await HTTPClientPool.get_proxy_client(proxy_config)
|
||||||
return await client.post(
|
proxy_url = _coerce_proxy_url(proxy_config)
|
||||||
url,
|
safe_url = _redact_url(url)
|
||||||
headers=headers,
|
|
||||||
data=data,
|
last_exc: Exception | None = None
|
||||||
json=json_body,
|
# Only retry connection-level transient failures.
|
||||||
timeout=timeout_seconds,
|
for attempt in range(2):
|
||||||
)
|
if attempt:
|
||||||
|
await asyncio.sleep(0.25 * attempt)
|
||||||
|
try:
|
||||||
|
return await client.post(
|
||||||
|
url,
|
||||||
|
headers=headers,
|
||||||
|
data=data,
|
||||||
|
json=json_body,
|
||||||
|
timeout=timeout_seconds,
|
||||||
|
)
|
||||||
|
except httpx.ConnectError as e:
|
||||||
|
last_exc = e
|
||||||
|
logger.warning(
|
||||||
|
"OAuth token POST connect error (attempt={}/2) url={} host={} proxy={} err_chain={} err={!r}",
|
||||||
|
attempt + 1,
|
||||||
|
safe_url,
|
||||||
|
urlsplit(url).netloc,
|
||||||
|
proxy_url,
|
||||||
|
_format_exc_chain(e),
|
||||||
|
e,
|
||||||
|
)
|
||||||
|
if attempt == 0:
|
||||||
|
continue
|
||||||
|
raise
|
||||||
|
except httpx.TimeoutException as e:
|
||||||
|
last_exc = e
|
||||||
|
logger.warning(
|
||||||
|
"OAuth token POST timeout (attempt={}/2) url={} host={} proxy={} err_chain={} err={!r}",
|
||||||
|
attempt + 1,
|
||||||
|
safe_url,
|
||||||
|
urlsplit(url).netloc,
|
||||||
|
proxy_url,
|
||||||
|
_format_exc_chain(e),
|
||||||
|
e,
|
||||||
|
)
|
||||||
|
# Retry only the first time for timeouts.
|
||||||
|
if attempt == 0:
|
||||||
|
continue
|
||||||
|
raise
|
||||||
|
except httpx.RequestError as e:
|
||||||
|
# Other request-level errors (proxy, TLS, etc). Log and re-raise.
|
||||||
|
last_exc = e
|
||||||
|
logger.error(
|
||||||
|
"OAuth token POST request error url={} host={} proxy={} err_chain={} err={!r}",
|
||||||
|
safe_url,
|
||||||
|
urlsplit(url).netloc,
|
||||||
|
proxy_url,
|
||||||
|
_format_exc_chain(e),
|
||||||
|
e,
|
||||||
|
)
|
||||||
|
raise
|
||||||
|
|
||||||
|
# Should not be reachable.
|
||||||
|
assert last_exc is not None
|
||||||
|
raise last_exc
|
||||||
|
|
||||||
|
|
||||||
def _tls_client_post_sync(
|
def _tls_client_post_sync(
|
||||||
|
|||||||
Reference in New Issue
Block a user