fish2018/pansou · error
[ ] 搜索请求返回 HTTP
Error message
[%s] 搜索请求返回 HTTP %d
What it means
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).
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
Example fix
// before
return nil, fmt.Errorf("[%s] 搜索请求返回 HTTP %d", p.Name(), resp.StatusCode)
// after
snip, _ := io.ReadAll(io.LimitReader(resp.Body, 256))
return nil, fmt.Errorf("[%s] 搜索请求返回 HTTP %d, body: %s", p.Name(), resp.StatusCode, snip) Defensive patterns
Strategy: retry
Validate before calling
// pre-flight status probe of the search endpoint
resp, err := client.Get(baseURL + "/search.php?searchsubmit=yes")
if err == nil {
resp.Body.Close()
if resp.StatusCode == http.StatusForbidden {
log.Printf("leso is bot-blocking this client")
}
} Try / catch
doc, err := plugin.fetchSearch(client, baseURL, keyword)
if err != nil {
var statusErr *fmt.Errorf
if errors.As(err, &statusErr) && strings.Contains(err.Error(), "HTTP 4") {
// 4xx: switch mirror or add credentials; don't retry immediately
return alternateMirrorSearch(keyword)
}
if strings.Contains(err.Error(), "HTTP 5") {
// 5xx: retry with backoff
time.Sleep(2 * time.Second)
return plugin.fetchSearch(client, baseURL, keyword)
}
return err
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
AI-assisted analysis of fish2018/pansou@beaa561337 (2026-09-07).
Data as JSON: /api/errors/6d0cbcd841701245.
Report an issue: GitHub.
Appendix: source
Thrown at plugin/leso/leso.go:153
form := url.Values{}
form.Set("mod", "forum")
form.Set("srchtxt", keyword)
form.Set("searchsubmit", "yes")
ctx, cancel := context.WithTimeout(context.Background(), requestTimeout)
defer cancel()
req, err := http.NewRequestWithContext(ctx, http.MethodPost, baseURL+"/search.php?searchsubmit=yes", strings.NewReader(form.Encode()))
if err != nil {
return nil, fmt.Errorf("[%s] 创建搜索请求失败: %w", p.Name(), err)
}
setHeaders(req, baseURL+"/")
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
resp, err := client.Do(req)
if err != nil {
return nil, fmt.Errorf("[%s] 搜索请求失败: %w", p.Name(), err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("[%s] 搜索请求返回 HTTP %d", p.Name(), resp.StatusCode)
}
doc, err := goquery.NewDocumentFromReader(io.LimitReader(resp.Body, 6<<20))
if err != nil {
return nil, fmt.Errorf("[%s] 解析搜索结果失败: %w", p.Name(), err)
}
return doc, nil
}
func (p *Plugin) fetchDetail(client *http.Client, item searchItem) (model.SearchResult, bool) {
ctx, cancel := context.WithTimeout(context.Background(), requestTimeout)
defer cancel()
req, err := http.NewRequestWithContext(ctx, http.MethodGet, item.detailURL, nil)
if err != nil {
return model.SearchResult{}, false
}
setHeaders(req, baseURL+"/")
resp, err := client.Do(req)
if err != nil {View on GitHub (pinned to beaa561337)