{"record":{"id":"c3e8ffd7db6b7f40","repo":"fish2018/pansou","slug":"s-http-d","errorCode":null,"errorMessage":"[%s] 搜索请求返回 HTTP %d","messagePattern":"\\[(.+?)\\] 搜索请求返回 HTTP (.+?)","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"plugin/5266ys/5266ys.go","lineNumber":186,"sourceCode":"\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"[%s] 编码搜索关键词失败: %w\", p.Name(), err)\n\t}\n\tform := \"show=title%2Csmalltext&tempid=1&tbname=article&keyboard=\" + url.QueryEscape(string(encoded)) + \"&submit=\"\n\tctx, cancel := context.WithTimeout(context.Background(), requestTimeout)\n\tdefer cancel()\n\treq, err := http.NewRequestWithContext(ctx, http.MethodPost, baseURL+searchPath, strings.NewReader(form))\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"[%s] 创建搜索请求失败: %w\", p.Name(), err)\n\t}\n\tsetHeaders(req, baseURL+\"/\")\n\treq.Header.Set(\"Content-Type\", \"application/x-www-form-urlencoded\")\n\tresp, err := client.Do(req)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"[%s] 搜索请求失败: %w\", p.Name(), err)\n\t}\n\tdefer resp.Body.Close()\n\tif resp.StatusCode != http.StatusOK {\n\t\treturn nil, fmt.Errorf(\"[%s] 搜索请求返回 HTTP %d\", p.Name(), resp.StatusCode)\n\t}\n\tbody, err := io.ReadAll(io.LimitReader(resp.Body, 4<<20))\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"[%s] 读取搜索结果失败: %w\", p.Name(), err)\n\t}\n\tdecoded, err := decodeGB18030(body)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"[%s] 解码搜索结果失败: %w\", p.Name(), err)\n\t}\n\tdoc, err := goquery.NewDocumentFromReader(strings.NewReader(decoded))\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"[%s] 解析搜索结果失败: %w\", p.Name(), err)\n\t}\n\treturn doc, nil\n}\n\nfunc (p *Plugin) fetchDetail(client *http.Client, detailURL string) ([]magnetItem, string, string) {\n\tctx, cancel := context.WithTimeout(context.Background(), requestTimeout)","sourceCodeStart":168,"sourceCodeEnd":204,"githubUrl":"https://github.com/fish2018/pansou/blob/beaa56133755a548ebc51b090b3816e2ae044aa6/plugin/5266ys/5266ys.go#L168-L204","documentation":"After a successful round trip, fetchSearch checks resp.StatusCode != http.StatusOK and returns this formatted message instead of an error value — the site answered, but not with 200. Since the search is a form POST to a scrape endpoint, non-200 usually means anti-bot blocking, a redirect to a captcha/verification page, or the endpoint path having changed on the site.","triggerScenarios":"The site returns 301/302 (redirect client doesn't follow to 200), 403 (WAF/anti-bot blocks the request headers or IP), 404 (searchPath changed on the site), 429 (rate limited), or 5xx (server error) for the POST to baseURL+searchPath.","commonSituations":"Too-frequent scraping triggers 429/403 rate limiting; the site added Cloudflare/WAF protection that rejects the default User-Agent; the site restructured its search URL so the old path 404s; the site is temporarily down (502/503).","solutions":["Log resp.StatusCode and, on 403/503, fetch the response body to look for Cloudflare/captcha markers.","Verify the search endpoint still exists by replaying the same POST with curl -v and the same headers setHeaders applies.","Add/refresh browser-like headers (User-Agent, Referer, Cookie) in setHeaders to pass anti-bot checks.","Respect rate limits: add delay/backoff between searches to avoid 429.","If the site moved paths, update the searchPath constant to the new endpoint."],"exampleFix":"// before\nif resp.StatusCode != http.StatusOK {\n    return nil, fmt.Errorf(\"[%s] 搜索请求返回 HTTP %d\", p.Name(), resp.StatusCode)\n}\n// after\nif resp.StatusCode != http.StatusOK {\n    snippet, _ := io.ReadAll(io.LimitReader(resp.Body, 512))\n    return nil, fmt.Errorf(\"[%s] 搜索请求返回 HTTP %d, body: %s\", p.Name(), resp.StatusCode, snippet)\n}","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"results, err := p.Search(ctx, keyword)\nif err != nil && strings.Contains(err.Error(), \"HTTP 4\") {\n    // 403/429: 等待退避后重试, 不要立即重复\n    time.Sleep(backoff)\n    results, err = p.Search(ctx, keyword)\n}","preventionTips":["Throttle request rate to avoid 429/403 rate limiting and WAF blocks.","Keep browser-like headers (User-Agent/Referer/Cookies) current to pass anti-bot checks.","Alert on repeated non-200 codes — it usually means the site changed or is blocking you.","Check the site manually in a browser when status codes change."],"tags":["go","http","scraping","anti-bot"],"backgroundTag":"http-non-200-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"}