fish2018/pansou · error

读取首页失败

Error message

读取首页失败: %w

What it means

Wraps any error from doLimitedRequest while fetching the xiaokupan homepage (https://xiaokupan.com/) inside discoverServerFunctionID. Discovery is the fallback path used when the cached server-function ID fails, so this error means the recovery step itself could not even download the homepage HTML needed to locate the entry JS asset.

Solutions

  1. Check the wrapped cause: 请求失败 → connectivity, HTTP 403 → anti-bot, HTTP 5xx → site down, timeout → slow site
  2. Verify with curl -v https://xiaokupan.com/ that the homepage is reachable from the host
  3. For 403, update request headers (User-Agent/Accept already set) or resolve IP blocking with the site
  4. Note the cached functionID remains in use until discovery succeeds — fix connectivity so future refreshes can run
  5. Retry later if the site is under maintenance
Defensive patterns

Strategy: fallback

Validate before calling

resp, err := http.Head("https://xiaokupan.com/")
if err != nil || resp.StatusCode != http.StatusOK {
    return errors.New("xiaokupan homepage unreachable; discovery will fail")
}
resp.Body.Close()

Try / catch

if strings.Contains(err.Error(), "读取首页失败") {
    // recovery path failed at the very first step; keep cached functionID
    // and fall back to other search sources
    return fallbackSearch(keyword)
}

Prevention

When it happens

Trigger: Homepage fetch fails via doLimitedRequest: network error (请求失败 wrapper), non-200 status (HTTP NNN wrapper), mid-body read failure, or homepage body exceeding maxDiscoveryBodySize (8MiB). Triggered when searchImpl detects a stale/broken function ID and calls refreshServerFunctionID -> discoverServerFunctionID.

Common situations: Site down or DNS unreachable at the moment of recovery; Cloudflare/WAF blocking the programmatic homepage request (403); homepage served a 5xx during maintenance; very slow homepage load hitting the 30s timeout.

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/1e552f30d0c94e3f. Report an issue: GitHub.

Appendix: source

Thrown at plugin/xiaokupan/xiaokupan.go:233

	}
	p.serverFunctionID = discoveredID
	return discoveredID, nil
}

func (p *XiaokupanPlugin) discoverServerFunctionID(client *http.Client) (string, error) {
	ctx, cancel := context.WithTimeout(context.Background(), requestTimeout)
	defer cancel()

	homeURL := strings.TrimRight(p.baseURL, "/") + "/"
	req, err := http.NewRequestWithContext(ctx, http.MethodGet, homeURL, nil)
	if err != nil {
		return "", err
	}
	req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36")
	req.Header.Set("Accept", "text/html,application/xhtml+xml")
	homeBody, err := doLimitedRequest(client, req, maxDiscoveryBodySize)
	if err != nil {
		return "", fmt.Errorf("读取首页失败: %w", err)
	}

	assetPath := string(indexAssetPattern.Find(homeBody))
	if assetPath == "" {
		return "", fmt.Errorf("首页未找到入口脚本")
	}
	assetReq, err := http.NewRequestWithContext(ctx, http.MethodGet, strings.TrimRight(p.baseURL, "/")+assetPath, nil)
	if err != nil {
		return "", err
	}
	assetReq.Header.Set("User-Agent", req.Header.Get("User-Agent"))
	assetReq.Header.Set("Referer", homeURL)
	assetBody, err := doLimitedRequest(client, assetReq, maxDiscoveryBodySize)
	if err != nil {
		return "", fmt.Errorf("读取入口脚本失败: %w", err)
	}

	routeIndex := strings.Index(string(assetBody), "/s/$query")

View on GitHub (pinned to beaa561337)