{"record":{"id":"6d0cbcd841701245","repo":"fish2018/pansou","slug":"s-http-d-6d0cbc","errorCode":null,"errorMessage":"[%s] 搜索请求返回 HTTP %d","messagePattern":"\\[(.+?)\\] 搜索请求返回 HTTP (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"plugin/leso/leso.go","lineNumber":153,"sourceCode":"\tform := url.Values{}\n\tform.Set(\"mod\", \"forum\")\n\tform.Set(\"srchtxt\", keyword)\n\tform.Set(\"searchsubmit\", \"yes\")\n\tctx, cancel := context.WithTimeout(context.Background(), requestTimeout)\n\tdefer cancel()\n\treq, err := http.NewRequestWithContext(ctx, http.MethodPost, baseURL+\"/search.php?searchsubmit=yes\", strings.NewReader(form.Encode()))\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\tdoc, err := goquery.NewDocumentFromReader(io.LimitReader(resp.Body, 6<<20))\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, item searchItem) (model.SearchResult, bool) {\n\tctx, cancel := context.WithTimeout(context.Background(), requestTimeout)\n\tdefer cancel()\n\treq, err := http.NewRequestWithContext(ctx, http.MethodGet, item.detailURL, nil)\n\tif err != nil {\n\t\treturn model.SearchResult{}, false\n\t}\n\tsetHeaders(req, baseURL+\"/\")\n\tresp, err := client.Do(req)\n\tif err != nil {","sourceCodeStart":135,"sourceCodeEnd":171,"githubUrl":"https://github.com/fish2018/pansou/blob/beaa56133755a548ebc51b090b3816e2ae044aa6/plugin/leso/leso.go#L135-L171","documentation":"fetchSearch rejects any non-200 status from the leso search endpoint with this message, including the plugin name and the numeric status. The server responded, but the search POST was not accepted (anti-bot challenge, rate limit, moved endpoint, server error).","triggerScenarios":"client.Do succeeded but resp.StatusCode != http.StatusOK — e.g. Discuz-style forum returns 403 for bot traffic, 301 to a new domain not followed, 429 rate limit, or 5xx outage.","commonSituations":"Leso mirror enabled anti-bot/Cloudflare protection; forum requires login/cookies for search; rate limiting after aggressive crawling; mirror domain changed so old URL redirects or 404s.","solutions":["Log a body snippet with the status to see whether it's a captcha, redirect, or error page","Send realistic browser headers (User-Agent, Referer, cookies) to pass bot checks","Update the mirror's base URL if the site moved or the search path changed","Back off and retry on 429/5xx; reduce crawl rate to avoid throttling","If a login is now required, supply session cookies in the client's Jar"],"exampleFix":"// before\nreturn nil, fmt.Errorf(\"[%s] 搜索请求返回 HTTP %d\", p.Name(), resp.StatusCode)\n// after\nsnip, _ := io.ReadAll(io.LimitReader(resp.Body, 256))\nreturn nil, fmt.Errorf(\"[%s] 搜索请求返回 HTTP %d, body: %s\", p.Name(), resp.StatusCode, snip)","handlingStrategy":"retry","validationCode":"// pre-flight status probe of the search endpoint\nresp, err := client.Get(baseURL + \"/search.php?searchsubmit=yes\")\nif err == nil {\n    resp.Body.Close()\n    if resp.StatusCode == http.StatusForbidden {\n        log.Printf(\"leso is bot-blocking this client\")\n    }\n}","typeGuard":null,"tryCatchPattern":"doc, err := plugin.fetchSearch(client, baseURL, keyword)\nif err != nil {\n    var statusErr *fmt.Errorf\n    if errors.As(err, &statusErr) && strings.Contains(err.Error(), \"HTTP 4\") {\n        // 4xx: switch mirror or add credentials; don't retry immediately\n        return alternateMirrorSearch(keyword)\n    }\n    if strings.Contains(err.Error(), \"HTTP 5\") {\n        // 5xx: retry with backoff\n        time.Sleep(2 * time.Second)\n        return plugin.fetchSearch(client, baseURL, keyword)\n    }\n    return err\n}","preventionTips":["Keep cookies/session (cookiejar) since Discuz forums may require them","Throttle request rate to avoid 429s","Track mirror domains and update config when they move","Handle 3xx explicitly if the client does not follow redirects","Log a body snippet on non-200 for triage"],"tags":["go","http","status-code","scraping"],"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"}