fish2018/pansou · error

请求失败

Error message

请求失败: %w

What it means

fetchPage in the bixin plugin wraps any error from http.Client.Do after exhausting all retry attempts (p.retries). It means the HTTP transport itself failed — connection refused, DNS failure, TLS handshake error, or timeout — and retries (500ms apart) did not help. The original transport error is preserved via %w for errors.Is/As inspection.

Solutions

  1. Check basic connectivity to the bixin API host (curl the endpoint) to rule out network/firewall issues.
  2. Inspect the wrapped error with errors.Is/As (e.g. net.Error timeout, *url.Error) to identify the transport root cause.
  3. Increase p.retries or backoff duration to tolerate transient network blips.
  4. Verify proxy environment variables (HTTP_PROXY/HTTPS_PROXY) and DNS resolution.

Example fix

// before
return nil, false, fmt.Errorf("请求失败: %w", err)
// after
var netErr net.Error
if errors.As(err, &netErr) && netErr.Timeout() {
    return nil, false, fmt.Errorf("请求超时(已重试%d次): %w", p.retries, err)
}
return nil, false, fmt.Errorf("请求失败: %w", err)
Defensive patterns

Strategy: retry

Validate before calling

// caller-side preflight
req, _ := http.NewRequest("GET", apiURL, nil)
resp, err := http.DefaultClient.Do(req)
if err != nil { log.Printf("bixin API unreachable: %v", err) } else { resp.Body.Close() }

Try / catch

results, err := plugin.Search(ctx, keyword)
if err != nil {
    var netErr net.Error
    if errors.As(err, &netErr) && netErr.Timeout() {
        // degrade gracefully: return cached or empty results
    } else if errors.Is(err, context.DeadlineExceeded) {
        // surface 'search timed out' to user
    }
}

Prevention

When it happens

Trigger: client.Do(req) returns a non-nil err on the final retry iteration (i == p.retries) inside fetchPage; e.g. the bixin API host is unreachable, DNS fails, TLS fails, or the request times out.

Common situations: API host blocked or offline, corporate proxy/firewall blocking outbound HTTPS, DNS misconfiguration, network outage, or too-low p.retries for a flaky network.

Related errors


AI-assisted analysis of fish2018/pansou@beaa561337 (2026-09-07). Data as JSON: /api/errors/cd520b6ab2150723. Report an issue: GitHub.

Appendix: source

Thrown at plugin/bixin/bixin.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)