fish2018/pansou · error

创建搜索请求失败

Error message

创建搜索请求失败: %w

What it means

After resolving the redirect target, searchPage builds a second http.NewRequest for the actual results page. If the searchURL assembled from the Location header is malformed (bad scheme, invalid characters, empty host after string concatenation), http.NewRequest fails and the error is wrapped as "创建搜索请求失败".

Solutions

  1. Log the failing searchURL value to inspect the malformed URL.
  2. Use net/url to parse the Location and ResolveReference against the base URL instead of string concatenation.
  3. url.QueryEscape / path escaping for any user-derived parts embedded in the URL.
  4. Validate that p.currentBaseURL includes the correct scheme (https://).

Example fix

// before
searchURL = p.currentBaseURL + "/" + strings.TrimPrefix(location, "/")
// after
base, _ := url.Parse(p.currentBaseURL)
ref, err := url.Parse(location)
if err != nil {
    return nil, fmt.Errorf("解析重定向URL失败: %w", err)
}
searchURL = base.ResolveReference(ref).String()
Defensive patterns

Strategy: validation

Validate before calling

// Go: validate the URL before constructing the request
u, err := url.Parse(searchURL)
if err != nil || u.Scheme == "" || u.Host == "" {
    return nil, fmt.Errorf("invalid searchURL: %q", searchURL)
}

Try / catch

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

Prevention

When it happens

Trigger: http.NewRequest("GET", searchURL, nil) returns a url.Parse error — typically because the Location header contained a malformed relative path that p.currentBaseURL + "/" concatenation turned into an invalid URL, or the header contained spaces/illegal characters.

Common situations: Upstream returns an unexpected relative Location (e.g. containing characters needing escaping, or protocol-relative "//host/..." mishandled by naive concatenation); base URL misconfigured with wrong scheme; site change alters Location format.

Understand the failure class

Background: "Invalid URL" errors: why new URL(), URI.parse, and reqwest::Url reject your string — missing scheme, whitespace, and bad path format — this error's family across 39 libraries.

Related errors


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

Appendix: source

Thrown at plugin/panwiki/panwiki.go:234

	}
	
	// 如果不是第一页,修改URL中的page参数
	if page > 1 {
		if strings.Contains(searchURL, "searchid=") {
			// 提取searchid并构建分页URL
			re := regexp.MustCompile(`searchid=(\d+)`)
			matches := re.FindStringSubmatch(searchURL)
			if len(matches) > 1 {
				searchid := matches[1]
				searchURL = fmt.Sprintf("%s/search.php?mod=forum&searchid=%s&orderby=lastpost&ascdesc=desc&searchsubmit=yes&page=%d", p.currentBaseURL, searchid, page)
			}
		}
	}
	
	// Step 2: 请求实际的搜索结果页面
	req2, err := http.NewRequest("GET", searchURL, nil)
	if err != nil {
		return nil, fmt.Errorf("创建搜索请求失败: %w", err)
	}
	
	p.setRequestHeaders(req2)
	
	resp2, err := client.Do(req2)
	if err != nil {
		return nil, fmt.Errorf("搜索请求失败: %w", err)
	}
	defer resp2.Body.Close()
	
	if resp2.StatusCode != http.StatusOK {
		return nil, fmt.Errorf("搜索请求返回状态码: %d", resp2.StatusCode)
	}
	
	// 解析搜索结果
	doc, err := goquery.NewDocumentFromReader(resp2.Body)
	if err != nil {
		return nil, fmt.Errorf("解析HTML失败: %w", err)

View on GitHub (pinned to beaa561337)