fish2018/pansou · error
请求失败
Error message
请求失败: %w
What it means
pan666's fetchPage returns this when client.Do(req) fails on the final retry attempt (i == p.retries). Earlier failures sleep 500ms and retry; once retries are exhausted the transport error (DNS, timeout, connection refused, TLS) is wrapped and returned. The req object is reused across attempts.
Solutions
- Inspect the wrapped transport error to identify DNS vs timeout vs TLS
- curl the same URL from the host to confirm reachability
- Increase the http.Client timeout if deadline exceeded
- If the host blocks spoofed headers, stop sending the random X-Forwarded-For header
Example fix
// before
resp, err = client.Do(req)
if err != nil {
if i == p.retries { return nil, false, fmt.Errorf("请求失败: %w", err) }
// after
resp, err = client.Do(req)
if err != nil {
if i == p.retries { return nil, false, fmt.Errorf("请求失败 after %d tries: %w", p.retries+1, err) } Defensive patterns
Strategy: retry
Validate before calling
func pan666Reachable() error {
c, err := net.DialTimeout("tcp", "pan666.example:443", 3*time.Second)
if err != nil { return err }
c.Close()
return nil
} Try / catch
if err != nil {
var netErr net.Error
if errors.As(err, &netErr) && netErr.Timeout() {
client.Timeout = 30 * time.Second // retry with longer timeout
}
return err
} Prevention
- Set a realistic client timeout for slow upstreams
- Log the wrapped transport error type to distinguish DNS/TLS/timeout
- Pre-check DNS resolution in constrained environments
- Avoid spoofed headers that some hosts reject outright
When it happens
Trigger: client.Do returns err on every attempt of the retry loop: unreachable host, DNS failure, TLS handshake error, context deadline exceeded, or connection reset before any response.
Common situations: pan666 API domain blocked or DNS-poisoned in the region; no outbound network in the deployment environment; server drops requests with the spoofed X-Forwarded-For header; client timeout too short for a slow upstream.
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/ecdb3f840f3bbd14.
Report an issue: GitHub.
Appendix: source
Thrown at plugin/pan666/pan666.go:207
req.Header.Set("User-Agent", getRandomUA())
req.Header.Set("X-Forwarded-For", generateRandomIP())
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("Sec-Fetch-Dest", "empty")
req.Header.Set("Sec-Fetch-Mode", "cors")
req.Header.Set("Sec-Fetch-Site", "same-origin")
var resp *http.Response
var responseBody []byte
// 重试逻辑
for i := 0; i <= p.retries; i++ {
// 发送请求
resp, err = client.Do(req)
if err != nil {
if i == p.retries {
return nil, false, fmt.Errorf("请求失败: %w", err)
}
time.Sleep(500 * time.Millisecond)
continue
}
defer resp.Body.Close()
// 读取响应体
responseBody, err = io.ReadAll(resp.Body)
if err != nil {
if i == p.retries {
return nil, false, fmt.Errorf("读取响应失败: %w", err)
}
time.Sleep(500 * time.Millisecond)
continue
}
// 状态码检查View on GitHub (pinned to beaa561337)