fish2018/pansou · error
[ ] 网盘第 页请求失败
Error message
[%s] %s网盘第%d页请求失败: %w
What it means
fetchSinglePageWithType wraps errors from doRequestWithRetry, which performs the actual HTTP GET to sdso.top with up to 3 attempts (exponential backoff). This error means the request failed on every attempt — network-level failure, timeout (30s context), TLS error, or every attempt returned a non-200 status.
Solutions
- Test reachability: curl -v https://sdso.top/api/sd/search?name=test&pageNo=1&from=baidu.
- Check for 403/429 responses — slow down or rotate IP/User-Agent if the site is rate-limiting.
- Increase the 30s context timeout or add more retries if the network is slow but healthy.
- Verify DNS/proxy configuration on the host (HTTP_PROXY/HTTPS_PROXY env, /etc/resolv.conf).
- Inspect the wrapped lastErr in the error message for the concrete transport cause.
Example fix
// before
client := &http.Client{} // no proxy support
// after
client := &http.Client{
Transport: &http.Transport{
Proxy: http.ProxyFromEnvironment,
TLSHandshakeTimeout: 10 * time.Second,
},
} Defensive patterns
Strategy: retry
Validate before calling
conn, err := net.DialTimeout("tcp", "sdso.top:443", 5*time.Second)
if err != nil { /* skip source: unreachable */ } Try / catch
results, err := plugin.Search(ctx, keyword)
if err != nil && strings.Contains(err.Error(), "重试") {
// transport failed after retries; back off before next attempt
time.Sleep(5 * time.Second)
} Prevention
- Configure HTTP proxy env vars on hosts behind firewalls
- Keep the 30s request timeout but tolerate slow networks with retries
- Cap pages-per-type to limit exposure to transient failures
- Check the wrapped lastErr for the concrete transport cause
When it happens
Trigger: client.Do fails 3 consecutive times for a page request: DNS resolution failure, connection refused/reset, TLS handshake error, the 30-second context deadline expiring, or repeated non-200 responses (note: non-200 bodies are also treated as retryable failures inside doRequestWithRetry).
Common situations: sdso.top is down or blocking the client; no outbound internet on the deployment host; a slow connection exceeding the 30s timeout; GFW/network filtering of the domain; the server returning 403/429 on all retries due to rate limiting.
Understand the failure class
Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.
Related errors
AI-assisted analysis of fish2018/pansou@beaa561337 (2026-09-07).
Data as JSON: /api/errors/069cf75405b72873.
Report an issue: GitHub.
Appendix: source
Thrown at plugin/sdso/sdso.go:251
defer cancel()
// 3. 创建请求对象
req, err := http.NewRequestWithContext(ctx, "GET", searchURL, nil)
if err != nil {
return nil, fmt.Errorf("[%s] %s网盘第%d页创建请求失败: %w", p.Name(), fromType, pageNo, err)
}
// 4. 设置请求头
req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36")
req.Header.Set("Accept", "application/json, text/plain, */*")
req.Header.Set("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8")
req.Header.Set("Connection", "keep-alive")
req.Header.Set("Referer", "https://sdso.top/")
// 5. 发送HTTP请求(带重试机制)
resp, err := p.doRequestWithRetry(req, client)
if err != nil {
return nil, fmt.Errorf("[%s] %s网盘第%d页请求失败: %w", p.Name(), fromType, pageNo, err)
}
defer resp.Body.Close()
// 6. 检查状态码
if resp.StatusCode != 200 {
return nil, fmt.Errorf("[%s] %s网盘第%d页返回状态码: %d", p.Name(), fromType, pageNo, resp.StatusCode)
}
// 7. 解析响应
var apiResp APIResponse
if err := json.NewDecoder(resp.Body).Decode(&apiResp); err != nil {
return nil, fmt.Errorf("[%s] %s网盘第%d页JSON解析失败: %w", p.Name(), fromType, pageNo, err)
}
// 8. 检查API响应状态
if apiResp.Code != 200 {
return nil, fmt.Errorf("[%s] %s网盘第%d页API错误: %s", p.Name(), fromType, pageNo, apiResp.Msg)
}View on GitHub (pinned to beaa561337)