fish2018/pansou · error

创建请求失败

Error message

创建请求失败: %w

What it means

In fetchSearchResults, http.NewRequestWithContext failed to construct the GET request for the search URL. This happens before any network I/O and usually means the URL is malformed (unparsable scheme/host) — often because keyword interpolation produced an invalid URL.

Solutions

  1. Validate cygBaseURL starts with http:// or https:// and is a parseable URL before building the request.
  2. Ensure url.QueryEscape is applied to the keyword (it is) and that no raw control characters enter the URL.
  3. Print the final searchURL on failure to spot malformed construction.
  4. Use url.Parse on the final URL as a pre-check and fail early with a clearer message.

Example fix

// before
req, err := http.NewRequestWithContext(ctx, "GET", searchURL, nil)
if err != nil {
    return nil, fmt.Errorf("创建请求失败: %w", err)
}
// after
if u, perr := url.Parse(searchURL); perr != nil || u.Scheme == "" || u.Host == "" {
    return nil, fmt.Errorf("无效的搜索URL: %q (%v)", searchURL, perr)
}
req, err := http.NewRequestWithContext(ctx, "GET", searchURL, nil)
if err != nil {
    return nil, fmt.Errorf("创建请求失败: %w", err)
}
Defensive patterns

Strategy: validation

Validate before calling

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

Try / catch

results, err := plugin.SearchWithResult(ctx, opts)
if err != nil && strings.Contains(err.Error(), "创建请求失败") {
    // configuration problem: check baseURL format before retrying
}

Prevention

When it happens

Trigger: searchImpl passes a searchURL built from cygBaseURL plus query params that http.NewRequestWithContext cannot parse — e.g. empty base URL, control characters in the keyword that survived QueryEscape, or a malformed base URL configuration.

Common situations: cygBaseURL configured without a scheme (missing https://) or with a typo; keyword containing newlines or control characters; empty configuration making the URL just the query string.

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

Appendix: source

Thrown at plugin/cyg/cyg.go:140

	// 3. 并发获取每个帖子的下载链接
	results := p.fetchDownloadLinksAsync(client, posts, keyword)

	// 4. 关键词过滤
	filteredResults := plugin.FilterResultsByKeyword(results, keyword)

	return filteredResults, nil
}

// fetchSearchResults 获取搜索结果列表
func (p *CygPlugin) fetchSearchResults(client *http.Client, searchURL string) ([]CygPost, error) {
	// 创建带超时的上下文
	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("创建请求失败: %w", err)
	}

	// 设置请求头
	p.setRequestHeaders(req)

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

	// 检查状态码
	if resp.StatusCode != 200 {
		return nil, fmt.Errorf("HTTP错误状态码: %d", resp.StatusCode)
	}

	// 解析响应

View on GitHub (pinned to beaa561337)