fish2018/pansou · error

[ ] 网盘第 页创建请求失败

Error message

[%s] %s网盘第%d页创建请求失败: %w

What it means

fetchSearchPage builds an http.NewRequestWithContext GET to the haisou search API and wraps any construction error with this message naming the plugin, pan type, and page number. This fires before any network traffic — it means the request object itself could not be created, almost always because the search URL was malformed (e.g. empty panType/keyword producing an invalid URL).

Solutions

  1. Log/inspect the constructed searchURL; pass it through url.Parse to see why it is invalid.
  2. URL-escape the keyword with url.QueryEscape before inserting into the URL template.
  3. Fix the panType/pageNo values being passed in (must be non-empty, positive).
  4. Verify the site base URL configured in the plugin is correct.

Example fix

// before
searchURL := fmt.Sprintf("%s/api/search?kw=%s&page=%d", base, keyword, pageNo)
// after
searchURL := fmt.Sprintf("%s/api/search?kw=%s&page=%d", base, url.QueryEscape(keyword), pageNo)
Defensive patterns

Strategy: validation

Validate before calling

if panType == "" || keyword == "" || pageNo < 1 {
    return errors.New("panType, keyword and pageNo must be valid before building the request")
}
searchURL := fmt.Sprintf("%s/api/search?kw=%s&page=%d", base, url.QueryEscape(keyword), pageNo)
if _, err := url.Parse(searchURL); err != nil {
    return fmt.Errorf("invalid search URL %q: %w", searchURL, err)
}

Try / catch

items, err := fetchSearchPage(panType, keyword, pageNo)
var urlErr *url.Error
if errors.As(err, &urlErr) {
    return fmt.Errorf("bad request URL: %w", err)
}

Prevention

When it happens

Trigger: Calling fetchSearchPage when http.NewRequestWithContext fails: invalid URL string from a bad panType/keyword/pageNo combination, unescaped control characters in the query, or an empty base URL.

Common situations: Query keywords containing characters not URL-encoded; site config with a wrong/empty base URL; a pan type constant typo producing a bad path; regression after URL template changes.

Understand the failure class

Background: "Invalid URL" / "URL cannot be empty": fix the malformed or missing URL behind request-construction failures — this error's family across 50 libraries.

Related errors


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

Appendix: source

Thrown at plugin/haisou/haisou.go:328

// fetchSearchPage 获取指定网盘类型的单页搜索结果
func (p *HaisouPlugin) fetchSearchPage(client *http.Client, keyword string, pageNo int, panType string) ([]ShareItem, error) {
	// 构建搜索URL
	searchURL := fmt.Sprintf("https://haisou.cc/api/pan/share/search?query=%s&scope=title&pan=%s&page=%d&filter_valid=true&filter_has_files=false",
		url.QueryEscape(keyword), panType, pageNo)

	if DebugLog {
		fmt.Printf("[%s] 请求%s网盘第%d页: %s\n", p.Name(), panType, pageNo, searchURL)
	}

	// 创建带超时的上下文
	ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
	defer cancel()

	// 创建请求对象
	req, err := http.NewRequestWithContext(ctx, "GET", searchURL, nil)
	if err != nil {
		return nil, fmt.Errorf("[%s] %s网盘第%d页创建请求失败: %w", p.Name(), panType, pageNo, err)
	}

	// 设置请求头
	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://haisou.cc/")

	// 发送HTTP请求(带重试机制)
	resp, err := p.doRequestWithRetry(req, client)
	if err != nil {
		return nil, fmt.Errorf("[%s] %s网盘第%d页请求失败: %w", p.Name(), panType, pageNo, err)
	}
	defer resp.Body.Close()

	// 检查状态码
	if resp.StatusCode != 200 {

View on GitHub (pinned to beaa561337)