{"record":{"id":"125fa19602389ccc","repo":"fish2018/pansou","slug":"http-d-s","errorCode":null,"errorMessage":"HTTP %d: %s","messagePattern":"HTTP (.+?): (.+?)","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"plugin/yingso/yingso.go","lineNumber":316,"sourceCode":"\tif payload != nil {\n\t\treq.Header.Set(\"Content-Type\", \"application/json\")\n\t}\n\n\tresp, err := client.Do(req)\n\tif err != nil {\n\t\treturn err\n\t}\n\tdefer resp.Body.Close()\n\n\tdata, err := io.ReadAll(io.LimitReader(resp.Body, maxResponseSize+1))\n\tif err != nil {\n\t\treturn err\n\t}\n\tif len(data) > maxResponseSize {\n\t\treturn fmt.Errorf(\"响应超过 %d 字节\", maxResponseSize)\n\t}\n\tif resp.StatusCode != http.StatusOK {\n\t\treturn fmt.Errorf(\"HTTP %d: %s\", resp.StatusCode, strings.TrimSpace(string(data)))\n\t}\n\tif err := jsonutil.Unmarshal(data, target); err != nil {\n\t\treturn fmt.Errorf(\"解析响应失败: %w\", err)\n\t}\n\treturn nil\n}\n\nfunc encryptPayload(payload interface{}, config apiConfig) (encryptedPayload, error) {\n\tno, err := randomToken(24)\n\tif err != nil {\n\t\treturn encryptedPayload{}, err\n\t}\n\tif config.Start < 0 || config.End <= config.Start || config.End > len(no) {\n\t\treturn encryptedPayload{}, fmt.Errorf(\"无效的加密区间 %d:%d\", config.Start, config.End)\n\t}\n\n\tencoded, err := jsonutil.MarshalString(payload)\n\tif err != nil {","sourceCodeStart":298,"sourceCodeEnd":334,"githubUrl":"https://github.com/fish2018/pansou/blob/beaa56133755a548ebc51b090b3816e2ae044aa6/plugin/yingso/yingso.go#L298-L334","documentation":"requestJSON requires an HTTP 200 status; any other status (redirects already followed, so typically 4xx/5xx, or envelopes like 403 from a WAF) produces this error with the status code and a trimmed snippet of the response body. It wraps transport-level failures of the underlying Yingso HTTP calls before JSON decoding is attempted.","triggerScenarios":"Any requestJSON call (fetchConfig GET /test, POST /search, POST /getKey) where resp.StatusCode != 200: server 5xx outages, 429 rate limiting from concurrent getKey calls, 403 from WAF/bot detection (Origin/Referer/UA checks failing), or 404 from a stale url_version path segment.","commonSituations":"Yingso API outage or maintenance (502/503); rate limiting under the plugin's 8-way concurrency (429); cloudflare/WAF challenge pages (403/503 with HTML body); the rotated url_version from fetchConfig produces 404 if config parsing went wrong.","solutions":["Read the status code and body snippet in the error: 429 → reduce maxKeyConcurrency or add backoff/retry; 403 → check WAF interception; 5xx → retry later.","Add retry with exponential backoff around requestJSON for 429/5xx statuses (with a retry budget, e.g. 2 attempts).","Reduce concurrency (maxKeyConcurrency=8, yingso.go:29) if 429s appear during bulk getKey resolution.","Confirm the URL — a 404 usually means url_version from /test is stale or the path template changed; re-run fetchConfig.","If a WAF challenge (HTML in body) is returned, update headers (User-Agent, Origin, Referer) to match what the official web client sends."],"exampleFix":"// before\nif resp.StatusCode != http.StatusOK {\n\treturn fmt.Errorf(\"HTTP %d: %s\", resp.StatusCode, strings.TrimSpace(string(data)))\n}\n// after\nif resp.StatusCode != http.StatusOK {\n\tif resp.StatusCode == http.StatusTooManyRequests || resp.StatusCode >= 500 {\n\t\treturn errRetryable // let caller back off and retry\n\t}\n\treturn fmt.Errorf(\"HTTP %d: %s\", resp.StatusCode, strings.TrimSpace(string(data)))\n}","handlingStrategy":"retry","validationCode":"// probe availability before real calls\nresp, err := client.Get(apiBaseURL + \"/test\")\nif err != nil || resp.StatusCode != http.StatusOK {\n\tlog.Printf(\"yingso endpoint unhealthy (status=%v)\", statusOrNil(resp))\n}","typeGuard":null,"tryCatchPattern":"results, err := p.searchImpl(client, keyword, ext)\nif err != nil {\n\tvar httpErr *HTTPStatusError\n\tif errors.As(err, &httpErr) && (httpErr.Status == 429 || httpErr.Status >= 500) {\n\t\ttime.Sleep(exponentialBackoff(attempt))\n\t\treturn p.searchImpl(client, keyword, ext)\n\t}\n\treturn nil, err\n}","preventionTips":["Retry 429/5xx with exponential backoff and a small retry budget.","Reduce maxKeyConcurrency (8) if rate-limit 429s occur during bulk resolution.","Keep request headers (User-Agent, Origin, Referer) aligned with the official web client to pass WAF checks.","Re-run fetchConfig when 404s appear — a stale url_version breaks endpoint paths.","Alert on sustained 5xx so API outages are distinguished from local misconfig."],"tags":["http","http-status","upstream","retry"],"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"}