diff --git a/app.py b/app.py index ec789fff..e1107abc 100755 --- a/app.py +++ b/app.py @@ -3574,23 +3574,49 @@ def register_with_email(): def _safe_http_get(url, params=None, timeout=10): """安全的 HTTP GET 请求(绕过 eventlet DNS 问题) - Eventlet 的 greendns 可能无法解析某些域名,使用 tpool 在原生线程中执行请求 + 使用 subprocess 调用 curl,完全绕过 Python/eventlet 的网络栈 """ - def _do_request(): - return requests.get(url, params=params, timeout=timeout) + import subprocess + import urllib.parse + + # 构建完整 URL + if params: + query_string = urllib.parse.urlencode(params) + full_url = f"{url}?{query_string}" + else: + full_url = url try: - # 检查是否在 eventlet 环境中 - import eventlet - if hasattr(eventlet, 'is_monkey_patched') and eventlet.is_monkey_patched('socket'): - # 使用 tpool 在原生线程中执行,绕过 eventlet 的 DNS - from eventlet import tpool - return tpool.execute(_do_request) - except ImportError: - pass + # 使用 curl 发起请求,绕过 eventlet DNS 问题 + result = subprocess.run( + ['curl', '-s', '-m', str(timeout), full_url], + capture_output=True, + text=True, + timeout=timeout + 5 + ) - # 非 eventlet 环境,直接请求 - return _do_request() + if result.returncode != 0: + print(f"❌ curl 请求失败: returncode={result.returncode}, stderr={result.stderr}") + return None + + # 返回一个模拟 Response 对象 + class MockResponse: + def __init__(self, text): + self.text = text + self.content = text.encode('utf-8') + self.encoding = 'utf-8' + + def json(self): + return json.loads(self.text) + + return MockResponse(result.stdout) + + except subprocess.TimeoutExpired: + print(f"❌ curl 请求超时: {full_url}") + return None + except Exception as e: + print(f"❌ curl 请求异常: {type(e).__name__}: {e}") + return None def get_wechat_access_token(code, appid=None, appsecret=None):