fish2018/pansou · error
[ ] 创建搜索请求失败
Error message
[%s] 创建搜索请求失败: %w
What it means
executeSearch wraps the error from http.NewRequestWithContext when building the POST request to the search endpoint. As with the token request, method/URL/body are constructed from constants and the token/keyword, so failure indicates the composed searchURL is not a valid URL. searchImpl aborts before any network I/O.
Solutions
- Log the composed searchURL and validate with url.Parse before constructing the request
- URL-escape the keyword (url.QueryEscape) and the token before interpolating into the query string
- Verify BaseURL and the search path format string in executeSearch are intact
Example fix
// before
searchURL := fmt.Sprintf("%s%s?DToken2=%s&...&wd=%s&...", BaseURL, searchPath, token, keyword)
// after
searchURL := fmt.Sprintf("%s%s?DToken2=%s&...&wd=%s&...", BaseURL, searchPath, url.QueryEscape(token), url.QueryEscape(keyword)) Defensive patterns
Strategy: validation
Validate before calling
u, err := url.Parse(searchURL)
if err != nil || u.Host == "" {
return fmt.Errorf("invalid search URL: %v", err)
} Try / catch
if err != nil {
return nil, fmt.Errorf("search request build failed: %w", err)
} Prevention
- Escape every interpolated value (keyword, token) with url.QueryEscape
- Build query strings with url.Values.Encode() instead of raw Sprintf
- Add a unit test composing searchURL with edge-case keywords (unicode, spaces, quotes)
When it happens
Trigger: http.NewRequestWithContext(ctx, "POST", searchURL, nil) errors — the fmt.Sprintf-composed searchURL (BaseURL + query string with DToken2/keyword interpolated) is malformed, e.g. unescaped control characters in the keyword.
Common situations: Search keyword containing raw newlines/control characters injected into the query string; BaseURL constant misconfigured; token value containing characters that break the URL.
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/14843833cef67634.
Report an issue: GitHub.
Appendix: source
Thrown at plugin/xys/xys.go:248
lastErr = err
}
return nil, fmt.Errorf("[%s] 重试 %d 次后仍然失败: %w", p.Name(), maxRetries, lastErr)
}
// executeSearch 执行搜索请求
func (p *XysPlugin) executeSearch(client *http.Client, token, keyword string) ([]model.SearchResult, error) {
// 构建搜索URL
searchURL := fmt.Sprintf("%s%s?DToken2=%s&requestID=undefined&mode=90002&stype=undefined&scope_content=0&wd=%s&uk=&page=1&limit=20&screen_filetype=",
BaseURL, SearchPath, token, url.QueryEscape(keyword))
// 创建带超时的上下文
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
req, err := http.NewRequestWithContext(ctx, "POST", searchURL, nil)
if err != nil {
return nil, fmt.Errorf("[%s] 创建搜索请求失败: %w", p.Name(), err)
}
// 设置完整的请求头
req.Header.Set("User-Agent", UserAgent)
req.Header.Set("Accept", "application/json, text/plain, */*")
req.Header.Set("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8")
req.Header.Set("Connection", "keep-alive")
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
req.Header.Set("Referer", BaseURL+"/")
req.Header.Set("Origin", BaseURL)
req.Header.Set("X-Requested-With", "XMLHttpRequest")
resp, err := p.doRequestWithRetry(req, client)
if err != nil {
return nil, fmt.Errorf("[%s] 搜索请求失败: %w", p.Name(), err)
}
defer resp.Body.Close()
View on GitHub (pinned to beaa561337)