fix(publish-gitea): urllib 连接失败时 curl -k 兜底并携带请求体
This commit is contained in:
@@ -58,11 +58,13 @@ def git_remote_info():
|
||||
class Api:
|
||||
def __init__(self, base, owner, repo, token, insecure):
|
||||
self.api = f'{base}/api/v1/repos/{owner}/{repo}'
|
||||
self.token = token
|
||||
self.headers = {'Authorization': f'token {token}'}
|
||||
self.ctx = ssl._create_unverified_context() if insecure else None
|
||||
|
||||
def request(self, method, path, data=None, headers=None, retries=4):
|
||||
"""发请求; 实例 TLS 间歇性抽风(SSL UNEXPECTED_EOF), 连接级错误自动重试"""
|
||||
"""发请求; 实例 TLS 间歇性抽风(SSL UNEXPECTED_EOF), 连接级错误自动重试,
|
||||
并改用 curl -k 兜底(urllib 的握手在该实例上可能持续失败)"""
|
||||
last = None
|
||||
for attempt in range(retries):
|
||||
req = urllib.request.Request(self.api + path, data=data, method=method,
|
||||
@@ -75,9 +77,39 @@ class Api:
|
||||
return e.code, json.loads(e.read() or b'{}')
|
||||
except (urllib.error.URLError, ssl.SSLError, OSError) as e:
|
||||
last = e
|
||||
try:
|
||||
status, body = self._curl(method, path, data, headers)
|
||||
if status > 0:
|
||||
return status, body
|
||||
except Exception as ce:
|
||||
last = ce
|
||||
time.sleep(1.0 + attempt)
|
||||
raise RuntimeError(f'Gitea 请求连续 {retries} 次失败: {last}')
|
||||
|
||||
def _curl(self, method, path, data=None, headers=None):
|
||||
"""curl 兜底: 返回 (status, json/None); 解析失败返回 (0, None) 交回上层重试"""
|
||||
cmd = ['curl', '-k', '-s', '-X', method, '-w', '\n%{http_code}']
|
||||
if data is not None:
|
||||
cmd += ['--data-binary', '@-']
|
||||
for key, value in self.headers.items():
|
||||
cmd += ['-H', f'{key}: {value}']
|
||||
for key, value in (headers or {}).items():
|
||||
cmd += ['-H', f'{key}: {value}']
|
||||
cmd.append(self.api + path)
|
||||
proc = subprocess.run(cmd, input=data, capture_output=True, timeout=600)
|
||||
out = proc.stdout.decode('utf-8', 'replace')
|
||||
body, _, code = out.rpartition('\n')
|
||||
try:
|
||||
status = int(code.strip())
|
||||
except ValueError:
|
||||
return 0, None
|
||||
if not body.strip():
|
||||
return status, None
|
||||
try:
|
||||
return status, json.loads(body)
|
||||
except ValueError:
|
||||
return status, {'raw': body}
|
||||
|
||||
def get_json(self, path):
|
||||
status, data = self.request('GET', path)
|
||||
return data if status == 200 else None
|
||||
|
||||
Reference in New Issue
Block a user