fish2018/pansou · error

创建GET请求失败

Error message

创建GET请求失败: %w

What it means

xdpan's fetchSearchResults builds the search GET request with http.NewRequestWithContext. If request construction fails (invalid method/URL, unparsable target), it wraps the error as this message. With a fixed 'GET' method this almost always means the assembled search URL is invalid.

Solutions

  1. Verify the xdpan baseURL configuration is set and is a valid absolute HTTP(S) URL.
  2. Trim whitespace/newlines from the configured base URL before use.
  3. Log the final searchURL to spot malformed composition (double schemes, missing host).
  4. Sanitize/strictly escape the keyword before inserting it into the query string.

Example fix

// before
searchURL := fmt.Sprintf("%s/search?page=1&k=%s&p=baidu", strings.TrimRight(p.baseURL, "/"), url.QueryEscape(keyword))
// after: validate the base URL first
base := strings.TrimSpace(strings.TrimRight(p.baseURL, "/"))
if u, err := url.Parse(base); err != nil || u.Scheme == "" || u.Host == "" {
	return nil, fmt.Errorf("无效的baseURL配置: %q", p.baseURL)
}
searchURL := fmt.Sprintf("%s/search?page=1&k=%s&p=baidu", base, url.QueryEscape(keyword))
Defensive patterns

Strategy: validation

Validate before calling

u, err := url.Parse(cfg.BaseURL)
if err != nil || u.Scheme == "" || u.Host == "" {
	return fmt.Errorf("invalid baseURL: %q", cfg.BaseURL)
}

Try / catch

results, err := pluginSearch(keyword)
if err != nil && strings.Contains(err.Error(), "创建GET请求失败") {
	// invalid URL — check and correct baseURL config before retrying
}

Prevention

When it happens

Trigger: http.NewRequestWithContext returns an error because the searchURL '%s/search?page=1&k=%s&p=baidu' is malformed — e.g. baseURL is empty, contains whitespace/control characters, or the URL-escaped keyword produced an invalid URL string.

Common situations: Missing or misconfigured xdpan baseURL (empty config field); trailing newline in a config value; keyword containing raw control characters; programmatic use passing a non-URL base.

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

Appendix: source

Thrown at plugin/xdpan/xdpan.go:103

	filteredResults := plugin.FilterResultsByKeyword(searchResults, keyword)
	if DebugLog {
		fmt.Printf("[xdpan] 关键词过滤后: 过滤前=%d, 过滤后=%d\n", len(searchResults), len(filteredResults))
	}

	return filteredResults, nil
}

// fetchSearchResults 获取搜索结果
func (p *XdpanPlugin) fetchSearchResults(client *http.Client, keyword string) ([]model.SearchResult, error) {
	// 构建搜索URL(只获取第一页)
	searchURL := fmt.Sprintf("%s/search?page=1&k=%s&p=baidu", strings.TrimRight(p.baseURL, "/"), url.QueryEscape(keyword))

	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("创建GET请求失败: %w", err)
	}

	p.setRequestHeaders(req)

	if DebugLog {
		fmt.Printf("[xdpan] 搜索URL: %s\n", searchURL)
	}

	resp, err := p.doRequestWithRetry(req, client)
	if err != nil {
		return nil, fmt.Errorf("GET请求失败: %w", err)
	}
	defer resp.Body.Close()

	if resp.StatusCode != http.StatusOK {
		return nil, fmt.Errorf("请求返回状态码: %d", resp.StatusCode)
	}

View on GitHub (pinned to beaa561337)