fish2018/pansou · error

[ ] 创建请求失败

Error message

[%s] 创建请求失败: %w

What it means

The ahhhhfs plugin's searchImpl wraps any error from http.NewRequestWithContext when building the GET search request to www.ahhhhfs.com as '[%s] 创建请求失败'. net/http validates the method, URL, and body at construction; with hardcoded 'GET' and a fixed searchURL, this only fires if the search URL is malformed (nil context, bad scheme, invalid characters in the URL).

Solutions

  1. Inspect the wrapped %w error — net/http states which part of the request is invalid.
  2. Ensure the search keyword is passed through url.QueryEscape when interpolating into searchURL.
  3. Run url.Parse(searchURL) before building the request and fail fast with a clear message on malformed URLs.
  4. Pin down where searchURL comes from (constant vs config) and validate it at plugin startup.

Example fix

// before
searchURL := "https://www.ahhhhfs.com/?s=" + keyword
req, err := http.NewRequestWithContext(ctx, "GET", searchURL, nil)
if err != nil {
    return nil, fmt.Errorf("[%s] 创建请求失败: %w", p.Name(), err)
}
// after
searchURL := "https://www.ahhhhfs.com/?s=" + url.QueryEscape(keyword)
req, err := http.NewRequestWithContext(ctx, "GET", searchURL, nil)
if err != nil {
    return nil, fmt.Errorf("[%s] 创建请求失败: %w", p.Name(), err)
}
Defensive patterns

Strategy: validation

Validate before calling

searchURL := "https://www.ahhhhfs.com/?s=" + url.QueryEscape(keyword)
if u, err := url.Parse(searchURL); err != nil || u.Host == "" {
    return fmt.Errorf("非法搜索URL: %q", searchURL)
}

Prevention

When it happens

Trigger: http.NewRequestWithContext(ctx, "GET", searchURL, nil) returns err — an unparseable searchURL (e.g. a keyword not properly URL-escaped producing spaces/control chars, or a broken baseURL constant) or a nil/invalid context.

Common situations: A developer edited the searchURL construction and forgot url.QueryEscape on the keyword, leaving raw spaces or CJK characters in the URL; a configuration-driven domain replacement injected an invalid host; manual refactor introduced a bad scheme.

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

Appendix: source

Thrown at plugin/ahhhhfs/ahhhhfs.go:166

		fmt.Printf("[%s] 搜索耗时: %v\n", p.Name(), time.Since(start))
	}()

	// 使用优化的客户端
	if p.optimizedClient != nil {
		client = p.optimizedClient
	}

	// 1. 构建搜索URL
	searchURL := fmt.Sprintf("https://www.ahhhhfs.com/?cat=&s=%s", url.QueryEscape(keyword))
	
	// 2. 创建带超时的上下文
	ctx, cancel := context.WithTimeout(context.Background(), DefaultTimeout)
	defer cancel()
	
	// 3. 创建请求
	req, err := http.NewRequestWithContext(ctx, "GET", searchURL, nil)
	if err != nil {
		return nil, fmt.Errorf("[%s] 创建请求失败: %w", p.Name(), err)
	}
	
	// 4. 设置完整的请求头(避免反爬虫)
	req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36")
	req.Header.Set("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8")
	req.Header.Set("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8")
	req.Header.Set("Connection", "keep-alive")
	req.Header.Set("Upgrade-Insecure-Requests", "1")
	req.Header.Set("Cache-Control", "max-age=0")
	req.Header.Set("Referer", "https://www.ahhhhfs.com/")
	
	// 5. 发送请求(带重试机制)
	resp, err := p.doRequestWithRetry(req, client)
	if err != nil {
		return nil, fmt.Errorf("[%s] 搜索请求失败: %w", p.Name(), err)
	}
	defer resp.Body.Close()
	

View on GitHub (pinned to beaa561337)