fix: detectHTMLResponse 跳过 XML 声明,添加 HTML 响应检测

- 在 json.Unmarshal 之前检测 HTML 响应
- detectHTMLResponse 先 strip <?xml...?> 声明再检查 HTML 前缀
- 返回中文诊断提示替代原始 JSON parse error
- 修复 Code Review: TestDetectHTMLResponse/XML_声明后跟_HTML

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
林迪文 2026-06-03 08:33:52 +08:00
parent 64ccd0466a
commit 044e736a1b
1 changed files with 47 additions and 0 deletions

View File

@ -107,6 +107,18 @@ func (c *Client) Do(method, path string, body interface{}, query url.Values) (*o
}
}
// Detect HTML response (avoid returning login page as normal data)
if detectHTMLResponse(respData) {
msg := "服务器返回了 HTML 页面而非 JSON 数据"
suggestion := suggestHTMLFix()
return output.ErrorEnvelope(resp.StatusCode, msg, suggestion),
&APIError{
StatusCode: resp.StatusCode,
Code: "HTML_RESPONSE",
Message: msg + "\n" + suggestion,
}
}
// Parse JSON
var raw map[string]interface{}
if err := json.Unmarshal(respData, &raw); err != nil {
@ -201,6 +213,41 @@ func (c *Client) Delete(path string, query url.Values) (*output.Envelope, error)
return c.Do("DELETE", path, nil, query)
}
// detectHTMLResponse detects whether the response body is an HTML page instead of JSON.
// It first strips any XML declaration (<?xml ...?>) before checking for HTML prefixes.
func detectHTMLResponse(data []byte) bool {
trimmed := bytes.TrimSpace(data)
if len(trimmed) == 0 {
return false
}
// Skip leading XML declaration (e.g., <?xml version="1.0"?>)
if bytes.HasPrefix(trimmed, []byte("<?")) {
if idx := bytes.Index(trimmed, []byte("?>")); idx != -1 {
trimmed = bytes.TrimSpace(trimmed[idx+2:])
}
}
if len(trimmed) == 0 {
return false
}
// Check for HTML document prefixes
prefixes := []string{"<!DOCTYPE", "<html", "<HTML", "<!doctype"}
for _, p := range prefixes {
if bytes.HasPrefix(trimmed, []byte(p)) {
return true
}
}
return false
}
func suggestHTMLFix() string {
return "API 返回了 HTML 页面而非 JSON 数据。" +
"可能原因:\n" +
" 1. 未登录或 Token 已过期 → 运行 gitlink-cli auth login\n" +
" 2. Token 权限不足 → 在 GitLink 平台重新生成 Token\n" +
" 3. API 端点不存在 → 检查路径是否正确\n" +
" 4. 使用 Shortcut 命令替代 Raw API → 运行 gitlink-cli --help 查看可用命令"
}
func suggestFix(code int) string {
switch code {
case 401: