fish2018/pansou · error

[ ] 创建请求失败

Error message

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

What it means

In ash's searchImpl, http.NewRequestWithContext fails while building the GET request for the search URL. The plugin wraps the error with its plugin name so the caller knows which plugin failed. This almost always means the search URL string is malformed (unparseable scheme/host) rather than a network problem.

Solutions

  1. Log/inspect the searchURL string right before NewRequestWithContext and validate it with url.Parse.
  2. Fix the base URL constant or configuration that supplies the host/path.
  3. Escape or trim user-controlled parts of the URL (url.PathEscape / url.QueryEscape) before building it.
  4. Reject empty/whitespace URLs early with an explicit validation error.

Example fix

// before
req, err := http.NewRequestWithContext(ctx, "GET", searchURL, nil)
// after
u, perr := url.Parse(searchURL)
if perr != nil || u.Scheme == "" || u.Host == "" {
    return nil, fmt.Errorf("[%s] 无效的搜索URL: %q", p.Name(), searchURL)
}
req, err := http.NewRequestWithContext(ctx, "GET", u.String(), nil)
Defensive patterns

Strategy: validation

Validate before calling

u, err := url.Parse(searchURL); if err != nil || u.Scheme == "" || u.Host == "" { return fmt.Errorf("invalid search URL: %q", searchURL) }

Try / catch

if err != nil {
    var uerr *url.Error
    if errors.As(err, &uerr) {
        log.Printf("bad URL %q: %v", uerr.URL, uerr.Err)
    }
    return err
}

Prevention

When it happens

Trigger: http.NewRequestWithContext(ctx, "GET", searchURL, nil) returns an error because searchURL cannot be parsed by url.Parse (invalid characters, bad scheme, control characters) — ash.go:84.

Common situations: Base URL constant edited to include a typo, spaces or full-width characters; config value interpolated into the URL containing unescaped characters; empty or corrupted base URL from a bad config merge.

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

Appendix: source

Thrown at plugin/ash/ash.go:84

// SearchWithResult 执行搜索并返回包含IsFinal标记的结果
func (p *AshPlugin) SearchWithResult(keyword string, ext map[string]interface{}) (model.PluginSearchResult, error) {
	return p.AsyncSearchWithResult(keyword, p.searchImpl, p.MainCacheKey, ext)
}

// searchImpl 实际的搜索实现(优化版本)
func (p *AshPlugin) searchImpl(client *http.Client, keyword string, ext map[string]interface{}) ([]model.SearchResult, error) {
	// 构建搜索URL
	searchURL := fmt.Sprintf("https://so.allsharehub.com/s/%s.html", url.QueryEscape(keyword))
	
	// 创建带超时的上下文(减少超时时间,提高响应速度)
	ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second)
	defer cancel()
	
	// 创建请求
	req, err := http.NewRequestWithContext(ctx, "GET", searchURL, nil)
	if err != nil {
		return nil, fmt.Errorf("[%s] 创建请求失败: %w", p.Name(), err)
	}
	
	// 设置请求头
	p.setRequestHeaders(req)
	
	// 发送请求(优化重试)
	resp, err := p.doRequestWithRetry(req, client)
	if err != nil {
		return nil, fmt.Errorf("[%s] 搜索请求失败: %w", p.Name(), err)
	}
	defer resp.Body.Close()
	
	// 检查状态码
	if resp.StatusCode != 200 {
		return nil, fmt.Errorf("[%s] 请求返回状态码: %d", p.Name(), resp.StatusCode)
	}
	
	// 读取响应(使用有限制的读取,避免读取过大内容)

View on GitHub (pinned to beaa561337)