fix: 上传与MediaPost链路增加直连和urllib兜底

This commit is contained in:
root authored and XianYuDaXian committed 2026-02-27 21:55:25 +08:00
1 parent ee64b02b9e
commit 2a063a08ed
2 files changed
+126 -10

No files matched your search

+38
View File
@@ -179,6 +179,44 @@ class AssetsUploadReverse:
"AssetsUpload transient exception, mark as retryable: "
f"{err_msg}"
)
# 部分 '"code"' 异常不会走到上面的降级分支,这里再强制兜底一次。
try:
response = await session.post(
UPLOAD_API,
headers=headers,
json=payload,
timeout=timeout,
)
if response.status_code == 200:
logger.info(
"AssetsUpload recovered by forced direct fallback after transient error"
)
return response
except Exception as forced_direct_err:
logger.warning(
"AssetsUpload forced direct fallback failed, "
f"error={forced_direct_err}"
)
try:
response = await AssetsUploadReverse._urllib_post(
url=UPLOAD_API,
headers=headers,
payload=payload,
timeout=timeout,
proxy_url=proxy_url,
)
if response.status_code == 200:
logger.info(
"AssetsUpload recovered by forced urllib fallback after transient error"
)
return response
except Exception as forced_urllib_err:
logger.warning(
"AssetsUpload forced urllib fallback failed, "
f"error={forced_urllib_err}"
)
raise UpstreamException(
message=f"AssetsUpload transient failure: {err_msg}",
details={"status": 403, "error": err_msg},
+88 -10
View File
@@ -2,6 +2,10 @@
Reverse interface: media post create.
"""
import asyncio
import json
import urllib.request
from dataclasses import dataclass
from typing import Any
from curl_cffi.requests import AsyncSession
@@ -16,6 +20,51 @@ MEDIA_POST_API = "https://grok.com/rest/media/post/create"
class MediaPostReverse:
"""/rest/media/post/create reverse interface."""
@dataclass
class _SimpleResponse:
status_code: int
headers: dict[str, str]
text: str
def json(self):
return json.loads(self.text or "{}")
@staticmethod
async def _urllib_post(
url: str, headers: dict[str, str], payload: dict[str, Any], timeout: int, proxy_url: str
) -> "MediaPostReverse._SimpleResponse":
body = json.dumps(payload).encode("utf-8")
opener = None
if proxy_url:
opener = urllib.request.build_opener(
urllib.request.ProxyHandler({"http": proxy_url, "https": proxy_url})
)
req = urllib.request.Request(url=url, data=body, headers=headers, method="POST")
def _do_post():
if opener is not None:
with opener.open(req, timeout=timeout) as resp:
status = int(getattr(resp, "status", 200) or 200)
raw_headers = {
str(k).lower(): str(v) for k, v in dict(resp.headers.items()).items()
}
text = resp.read().decode("utf-8", errors="replace")
return status, raw_headers, text
with urllib.request.urlopen(req, timeout=timeout) as resp:
status = int(getattr(resp, "status", 200) or 200)
raw_headers = {
str(k).lower(): str(v) for k, v in dict(resp.headers.items()).items()
}
text = resp.read().decode("utf-8", errors="replace")
return status, raw_headers, text
status, raw_headers, text = await asyncio.to_thread(_do_post)
return MediaPostReverse._SimpleResponse(
status_code=status,
headers=raw_headers,
text=text,
)
@staticmethod
async def request(
session: AsyncSession,
@@ -39,6 +88,7 @@ class MediaPostReverse:
# Get proxies
base_proxy = get_config("proxy.base_proxy_url")
proxies = {"http": base_proxy, "https": base_proxy} if base_proxy else None
proxy_url = base_proxy
# Build headers
headers = build_headers(
@@ -64,23 +114,51 @@ class MediaPostReverse:
browser = get_config("proxy.browser")
async def _do_request():
response = await session.post(
MEDIA_POST_API,
headers=headers,
json=payload,
timeout=timeout,
proxies=proxies,
impersonate=browser,
)
try:
response = await session.post(
MEDIA_POST_API,
headers=headers,
json=payload,
timeout=timeout,
proxies=proxies,
impersonate=browser,
)
except Exception as first_err:
logger.warning(
"MediaPostReverse primary request failed, fallback direct: "
f"error={first_err}"
)
try:
response = await session.post(
MEDIA_POST_API,
headers=headers,
json=payload,
timeout=timeout,
)
except Exception as second_err:
logger.warning(
"MediaPostReverse direct curl request failed, "
f"fallback urllib: error={second_err}"
)
response = await MediaPostReverse._urllib_post(
url=MEDIA_POST_API,
headers=headers,
payload=payload,
timeout=timeout,
proxy_url=proxy_url,
)
if response.status_code != 200:
content = ""
try:
content = await response.text()
content = (response.text or "").strip().replace("\n", " ")
except Exception:
pass
if len(content) > 300:
content = f"{content[:300]}...(len={len(content)})"
logger.error(
f"MediaPostReverse: Media post create failed, {response.status_code}",
"MediaPostReverse: Media post create failed, "
f"status={response.status_code}, body={content or '-'}",
extra={"error_type": "UpstreamException"},
)
raise UpstreamException(