POST 上游;重试覆盖【连接 + 完整读体】(含 SSL EOF、握手超时、对端断开、IncompleteRead), 对服务端明确响应(HTTPError,如 400)不重试。返回 (body_bytes, content_type)。
(url, data, headers, attempts=4, timeout=300)
| 234 | |
| 235 | |
| 236 | def http_post(url, data, headers, attempts=4, timeout=300): |
| 237 | """POST 上游;重试覆盖【连接 + 完整读体】(含 SSL EOF、握手超时、对端断开、IncompleteRead), |
| 238 | 对服务端明确响应(HTTPError,如 400)不重试。返回 (body_bytes, content_type)。""" |
| 239 | headers = {"User-Agent": UPSTREAM_UA, **headers} |
| 240 | for i in range(attempts): |
| 241 | req = urllib.request.Request(url, data=data, headers=headers) |
| 242 | try: |
| 243 | with urllib.request.urlopen(req, timeout=timeout) as r: |
| 244 | return r.read(), r.headers.get("Content-Type", "application/json") |
| 245 | except urllib.error.HTTPError: |
| 246 | raise |
| 247 | except Exception as e: |
| 248 | if i < attempts - 1: |
| 249 | log(f" ~ 上游连接抖动,重试 {i + 1}/{attempts - 1}: {e}") |
| 250 | time.sleep(0.8 * (i + 1)) |
| 251 | continue |
| 252 | raise |
| 253 | |
| 254 | |
| 255 | def open_stream(url, data, headers, attempts=4, timeout=300): |
no test coverage detected