fish2018/pansou · error

[ ] 创建请求失败

Error message

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

What it means

CldiPlugin.searchPage wraps http.NewRequestWithContext failures with the plugin name. This error is rare in practice: it fires only when the method/URL are syntactically invalid or the context is nil, since a malformed URL cannot be parsed into a *http.Request.

Solutions

  1. Log/print searchURL and validate it with url.Parse before constructing the request.
  2. Ensure the base URL includes a scheme (https://) and is properly URL-escaped.
  3. Fix the plugin config value holding the endpoint URL.

Example fix

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

Strategy: validation

Validate before calling

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

Type guard

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

Try / catch

results, err := plugin.Search(ctx, keyword)
if err != nil {
    if strings.Contains(err.Error(), "创建请求失败") {
        // config bug: log the URL and disable this plugin rather than retrying
    }
}

Prevention

When it happens

Trigger: http.NewRequestWithContext(ctx, "GET", searchURL, nil) returns err — searchURL is malformed (bad scheme, invalid characters, unparsable host) in searchPage.

Common situations: Configuration supplying a wrong or partially-updated base URL (e.g. missing scheme, spaces, or CJK characters not escaped), or a corrupted plugin config value.

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

Appendix: source

Thrown at plugin/cldi/cldi.go:136

	}

	// 3. 关键词过滤
	return plugin.FilterResultsByKeyword(allResults, keyword), nil
}

// searchPage 搜索指定页面
func (p *CldiPlugin) searchPage(client *http.Client, keyword string, page int) ([]model.SearchResult, error) {
	// 构建搜索URL (分类=0全部, 排序=2按添加时间)
	searchURL := fmt.Sprintf("%s/search-%s-0-2-%d.html", baseURL, url.QueryEscape(keyword), page)

	// 创建带超时的上下文
	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("[%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)