AutoRpa/rpa_selection/http_util.py

85 lines
2.7 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

from __future__ import annotations
import json
import time
from typing import Any
from urllib.parse import unquote
import requests
import urllib3
from mall_config import API_MAX_RETRIES, API_REQUEST_TIMEOUT_SECONDS, API_RETRY_BASE_SECONDS
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
def parse_cookie_value(raw_value: str | None) -> str:
if not raw_value:
return ""
return unquote(raw_value.strip().strip('"'))
def parse_response_json_or_raise(
response: requests.Response,
platform_name: str,
query_key: str,
) -> dict[str, Any]:
try:
payload_json = response.json()
except ValueError as exc:
raw_text = response.text or ""
cleaned_text = raw_text.lstrip("\ufeff").strip()
for prefix in (")]}',", "while(1);"):
if cleaned_text.startswith(prefix):
cleaned_text = cleaned_text[len(prefix) :].strip()
try:
payload_json = json.loads(cleaned_text)
except ValueError:
snippet = cleaned_text.replace("\r", " ").replace("\n", " ")[:200]
raise RuntimeError(
f"{platform_name} 接口返回非 JSON,查询键 {query_key},"
f"HTTP {response.status_code},响应片段:{snippet}"
) from exc
if not isinstance(payload_json, dict):
raise RuntimeError(
f"{platform_name} 接口 JSON 根结构异常,查询键 {query_key}:{type(payload_json)}"
)
return payload_json
def post_json_with_retry(
session: requests.Session,
url: str,
*,
platform_name: str,
query_key: str,
**request_kwargs: Any,
) -> dict[str, Any]:
last_error: Exception | None = None
for attempt in range(1, API_MAX_RETRIES + 1):
try:
response = session.post(
url,
timeout=API_REQUEST_TIMEOUT_SECONDS,
verify=False,
**request_kwargs,
)
response.raise_for_status()
return parse_response_json_or_raise(response, platform_name, query_key)
except (requests.RequestException, RuntimeError) as exc:
last_error = exc
if attempt >= API_MAX_RETRIES:
break
sleep_seconds = API_RETRY_BASE_SECONDS * attempt
print(
f"[重试] {platform_name} 查询键 {query_key} 第 {attempt}/{API_MAX_RETRIES} 次失败:"
f"{exc},{sleep_seconds:.1f} 秒后重试。"
)
time.sleep(sleep_seconds)
raise RuntimeError(
f"{platform_name} 接口请求失败,查询键 {query_key},"
f"重试 {API_MAX_RETRIES} 次后仍未成功:{last_error}"
) from last_error