{"record":{"id":"2df4f6753eefda53","repo":"fish2018/pansou","slug":"s-s","errorCode":null,"errorMessage":"请求失败，状态: %s, 详情: %s","messagePattern":"请求失败，状态: (.+?), 详情: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"plugin/panyq/panyq.go","lineNumber":674,"sourceCode":"\treq.Header.Set(\"User-Agent\", \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36\")\n\t\n\t// 发送请求\n\tresp, err := client.Do(req)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"请求网站首页失败: %w\", err)\n\t}\n\tdefer resp.Body.Close()\n\t\n\t// 检查状态码\n\tif resp.StatusCode != http.StatusOK {\n\t\t// 读取响应体以获取服务器返回的具体错误信息\n\t\tbodyBytes, err := io.ReadAll(resp.Body)\n\t\tif err != nil {\n\t\t\t// 如果连响应体都读取失败，则返回状态码错误并附上读取错误\n\t\t\treturn nil, fmt.Errorf(\"请求失败，状态码: %d，且读取响应体错误: %v\", resp.StatusCode, err)\n\t\t}\n\t\t// 将更详细的状态信息 (如 \"404 Not Found\") 和响应体内容一起作为错误返回\n\t\treturn nil, fmt.Errorf(\"请求失败，状态: %s, 详情: %s\", resp.Status, string(bodyBytes))\n\t}\n\n\tbody, err := io.ReadAll(resp.Body)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"读取响应失败: %w\", err)\n\t}\n\t\n\t// 提取JS文件路径\n\tjsRegex := regexp.MustCompile(`<script src=\"(/_next/static/[^\"]+\\.js)\"`)\n\tmatches := jsRegex.FindAllStringSubmatch(string(body), -1)\n\t\n\tif len(matches) == 0 {\n\t\treturn nil, fmt.Errorf(\"未找到JS文件\")\n\t}\n\t\n\t// 收集所有潜在的Action ID\n\tidSet := make(map[string]struct{})\n\tidRegex := regexp.MustCompile(`[\"\\']([a-f0-9]{40})[\"\\']{1}`)","sourceCodeStart":656,"sourceCodeEnd":692,"githubUrl":"https://github.com/fish2018/pansou/blob/beaa56133755a548ebc51b090b3816e2ae044aa6/plugin/panyq/panyq.go#L656-L692","documentation":"The homepage request returned a non-200 status code, and the response body was successfully read, so the function reports the full HTTP status line (e.g. \"404 Not Found\") together with the body contents. This is the primary diagnostic error for server-side rejections of the homepage request: 403/429 from anti-bot protection, 404/410 if the site restructured, 5xx if the origin is unhealthy.","triggerScenarios":"client.Do succeeded in findPotentialActionIDs but resp.StatusCode != http.StatusOK (e.g. 403 from Cloudflare, 429 rate limit, 502/503 from origin) and io.ReadAll(resp.Body) succeeded.","commonSituations":"Cloudflare/WAF challenge page returned for datacenter IPs; rate limiting after repeated calls to discoverActionIDs; site deployed a new version changing routes so old homepage paths 404; origin server temporarily down returning 5xx.","solutions":["Read the 详情 body: a Cloudflare challenge/HTML error page there tells you the request is being blocked — switch to a residential IP or solve the challenge.","If 429, back off and retry with a delay; add client-side rate limiting before calling discoverActionIDs.","If 404/410, update the plugin's configured base URL — the site likely restructured.","If 5xx, wait and retry; it is a server-side problem, not a client bug.","Send browser-like headers (already partially done) and verify the User-Agent isn't stale versus the WAF's expectations."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":"func isRetryableStatus(code int) bool {\n    switch code {\n    case http.StatusTooManyRequests,\n        http.StatusBadGateway,\n        http.StatusServiceUnavailable,\n        http.StatusGatewayTimeout:\n        return true\n    }\n    return code >= 500\n}","tryCatchPattern":"err := discoverActionIDs(ctx)\nif err != nil {\n    if strings.Contains(err.Error(), \"状态: 429\") || strings.Contains(err.Error(), \"状态: 5\") {\n        time.Sleep(backoff)\n        return discoverActionIDs(ctx)\n    }\n    if strings.Contains(err.Error(), \"状态: 404\") {\n        return fmt.Errorf(\"site layout changed; update base URL\")\n    }\n    return err\n}","preventionTips":["Rate-limit requests to the site and back off on 429.","Use residential IPs / solve challenges when a WAF blocks datacenter IPs.","Monitor the 详情 body in logs — it names the blocker (Cloudflare, nginx, etc.).","Keep the site URL current to avoid 404/410 after redeployments."],"tags":["http","anti-bot","scraping","go"],"backgroundTag":"http-error-response","analyzedSha":"beaa56133755a548ebc51b090b3816e2ae044aa6","analyzedAt":"2026-09-07T00:31:18.025Z","contentChangedAt":"2026-09-07T00:31:18.025Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}