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

  1. Test reachability: curl -v https://sdso.top/api/sd/search?name=test&pageNo=1&from=baidu.
  2. Check for 403/429 responses — slow down or rotate IP/User-Agent if the site is rate-limiting.
  3. Increase the 30s context timeout or add more retries if the network is slow but healthy.
  4. Verify DNS/proxy configuration on the host (HTTP_PROXY/HTTPS_PROXY env, /etc/resolv.conf).
  5. 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

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)