{"record":{"id":"52590c39902d3fd1","repo":"fish2018/pansou","slug":"s-http-d-52590c","errorCode":null,"errorMessage":"[%s] HTTP错误: %d","messagePattern":"\\[(.+?)\\] HTTP错误: (.+?)","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"plugin/yuhuage/yuhuage.go","lineNumber":113,"sourceCode":"\t\n\t// 发送HTTP请求\n\tresp, err := p.doRequestWithRetry(req, client)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"[%s] 搜索请求失败: %w\", p.Name(), err)\n\t}\n\tdefer resp.Body.Close()\n\t\n\tif resp.StatusCode == 429 {\n\t\tatomic.StoreInt32(&p.rateLimited, 1)\n\t\tgo func() {\n\t\t\ttime.Sleep(60 * time.Second)\n\t\t\tatomic.StoreInt32(&p.rateLimited, 0)\n\t\t}()\n\t\treturn nil, fmt.Errorf(\"[%s] 请求被限流\", p.Name())\n\t}\n\t\n\tif resp.StatusCode != 200 {\n\t\treturn nil, fmt.Errorf(\"[%s] HTTP错误: %d\", p.Name(), resp.StatusCode)\n\t}\n\t\n\t// 读取响应\n\tbody, err := io.ReadAll(resp.Body)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"[%s] 读取响应失败: %w\", p.Name(), err)\n\t}\n\t\n\t// 解析搜索结果\n\tresults, err := p.parseSearchResults(string(body))\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tif p.debugMode {\n\t\tlog.Printf(\"[YUHUAGE] 搜索完成，获得 %d 个结果\", len(results))\n\t}\n","sourceCodeStart":95,"sourceCodeEnd":131,"githubUrl":"https://github.com/fish2018/pansou/blob/beaa56133755a548ebc51b090b3816e2ae044aa6/plugin/yuhuage/yuhuage.go#L95-L131","documentation":"The yuhuage upstream returned an HTTP status other than 200 (and other than the already-handled 429). searchImpl rejects any non-200 response because it expects an HTML search page to parse. The actual code is included in the message.","triggerScenarios":"resp.StatusCode is not 200 and not 429 — commonly 403 (bot/WAF block), 5xx (server error), 404 (site restructured its search path), or 30x redirect responses.","commonSituations":"The site enabled Cloudflare bot detection returning 403; temporary upstream outages (502/503); the site changed BaseURL or search path so requests hit a 404; TLS/proxy middleware injecting error pages.","solutions":["Check the status code in the message: 403 means bot detection (update headers/cookies), 5xx means wait and retry.","Curl the search URL with the plugin's headers to reproduce and inspect the response.","Verify BaseURL (https://www.iyuhuage.fun) and SearchPath are still correct — update if the site moved.","Add retry/backoff for transient 5xx, similar to the existing 429 handling."],"exampleFix":"// before\nif resp.StatusCode != 200 {\n    return nil, fmt.Errorf(\"[%s] HTTP错误: %d\", p.Name(), resp.StatusCode)\n}\n// after\nif resp.StatusCode >= 500 {\n    return nil, retryableStatusError{code: resp.StatusCode}\n}\nif resp.StatusCode != 200 {\n    return nil, fmt.Errorf(\"[%s] HTTP错误: %d\", p.Name(), resp.StatusCode)\n}","handlingStrategy":"fallback","validationCode":"resp, err := http.Get(\"https://www.iyuhuage.fun/search/test-1-time.html\")\nif err == nil {\n    defer resp.Body.Close()\n    if resp.StatusCode != 200 {\n        // upstream unhealthy, use alternative plugin\n    }\n}","typeGuard":null,"tryCatchPattern":"results, err := plugin.Search(keyword, ext)\nif err != nil {\n    var httpErr struct{ code int }\n    if strings.Contains(err.Error(), \"HTTP错误: 403\") {\n        log.Printf(\"yuhuage bot-blocked, using fallback: %v\", err)\n        return fallbackResults, nil\n    }\n    if strings.Contains(err.Error(), \"HTTP错误: 5\") {\n        time.Sleep(backoff)\n        results, err = plugin.Search(keyword, ext)\n    }\n}","preventionTips":["Distinguish 4xx (config/bot issue) from 5xx (transient) before reacting.","Keep request headers current with real browser values.","Fall back to other search plugins on persistent non-200 responses."],"tags":["http","scraping","status-code"],"backgroundTag":"http-error-status","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"}