fish2018/pansou · error

[ ] 创建请求失败

Error message

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

What it means

http.NewRequestWithContext failed while building the GET request for the pianku search URL, so the request was never sent. This only happens with an invalid method/URL/body combination — most commonly a malformed searchURL.

Solutions

  1. Log the constructed searchURL when this error occurs
  2. Validate/escape the keyword with url.QueryEscape before building the URL
  3. Sanity-check the configured base URL (scheme, no whitespace)
  4. If the base URL comes from config, add a startup validation step

Example fix

// before
searchURL := baseURL + "/s.php?q=" + keyword
req, err := http.NewRequestWithContext(ctx, "GET", searchURL, nil)
// after
searchURL := baseURL + "/s.php?q=" + url.QueryEscape(keyword)
if _, perr := url.Parse(searchURL); perr != nil { return nil, fmt.Errorf("bad search url %q: %w", searchURL, perr) }
req, err := http.NewRequestWithContext(ctx, "GET", searchURL, 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)
}

Type guard

func validURL(s string) bool {
    u, err := url.Parse(s)
    return err == nil && (u.Scheme == "http" || u.Scheme == "https") && u.Host != ""
}

Try / catch

results, err := plugin.Search(keyword, ext)
if err != nil {
    if strings.Contains(err.Error(), "创建请求失败") {
        // malformed URL/config: fix base URL or keyword escaping, do not retry
    }
}

Prevention

When it happens

Trigger: searchURL built from config/base URL that is unparseable (control characters, missing scheme, bad query escaping of the keyword), causing url.Parse to fail inside NewRequestWithContext.

Common situations: Misconfigured base URL containing spaces or newlines; keyword with characters that break naive URL concatenation; empty base URL variable in config.

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

Appendix: source

Thrown at plugin/pianku/pianku.go:132

	if ext != nil {
		if titleEn, exists := ext["title_en"]; exists {
			if titleEnStr, ok := titleEn.(string); ok && titleEnStr != "" {
				searchKeyword = titleEnStr
			}
		}
	}
	
	// 构建请求URL
	searchURL := fmt.Sprintf("%s%s?wd=%s", BaseURL, SearchPath, url.QueryEscape(searchKeyword))
	
	// 创建带超时的上下文
	ctx, cancel := context.WithTimeout(context.Background(), TimeoutSeconds*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)
	
	// 发送HTTP请求(带重试机制)
	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)
	}
	
	// 解析HTML

View on GitHub (pinned to beaa561337)