fish2018/pansou · error
创建请求失败
Error message
创建请求失败: %w
What it means
bixin's fetchPage builds the search API URL (BaseURL + filter/include/page query params) and calls http.NewRequest("GET", apiURL, nil). If the URL cannot be parsed, it returns (nil, false, '创建请求失败: %w'). Note this call has no context deadline, unlike the ash plugin, so failures here are construction-time only.
Solutions
- Log apiURL on failure and validate with url.Parse before calling NewRequest.
- Fix the BaseURL constant/config supplying the endpoint host.
- Validate keyword (non-empty, no control chars) and rely on url.QueryEscape (already used) for interpolation.
- Add a context deadline via http.NewRequestWithContext so slow requests fail predictably too.
Example fix
// before
req, err := http.NewRequest("GET", apiURL, nil)
// after
u, perr := url.Parse(apiURL)
if perr != nil || u.Host == "" {
return nil, false, fmt.Errorf("创建请求失败: 无效URL %q: %w", apiURL, perr)
}
req, err := http.NewRequestWithContext(context.Background(), "GET", u.String(), nil) Defensive patterns
Strategy: validation
Validate before calling
u, err := url.Parse(apiURL); if err != nil || u.Scheme == "" || u.Host == "" { return fmt.Errorf("invalid api URL: %q", apiURL) } Try / catch
if err != nil {
var uerr *url.Error
if errors.As(err, &uerr) { log.Printf("bad URL: %q: %v", uerr.URL, uerr.Err) }
return nil, false, err
} Prevention
- Validate BaseURL at plugin init, not per request
- Keep using url.QueryEscape for keyword interpolation
- Trim configured hosts of whitespace
- Switch to http.NewRequestWithContext with a deadline
When it happens
Trigger: http.NewRequest returns an error because apiURL — built with url.QueryEscape(keyword) interpolated into BaseURL — is malformed: BaseURL empty or containing bad scheme/characters, or keyword escaping produced an invalid URL string — bixin.go:185.
Common situations: BaseURL constant mis-edited or overridden by an empty config value; keyword containing characters that break URL structure after naive interpolation; leading/trailing whitespace in a configured host.
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/ead58786f3467945.
Report an issue: GitHub.
Appendix: source
Thrown at plugin/bixin/bixin.go:185
// 按时间降序排序
sort.Slice(unique, func(i, j int) bool {
return unique[i].Datetime.After(unique[j].Datetime)
})
return unique
}
// fetchPage 获取指定页的搜索结果
func (p *BixinAsyncPlugin) fetchPage(client *http.Client, keyword string, offset int) ([]model.SearchResult, bool, error) {
// 构建API URL
apiURL := fmt.Sprintf("%s?filter[q]=%s&include=mostRelevantPost&page[offset]=%d&page[limit]=%d",
BaseURL, url.QueryEscape(keyword), offset, PageSize)
// 创建请求
req, err := http.NewRequest("GET", apiURL, nil)
if err != nil {
return nil, false, fmt.Errorf("创建请求失败: %w", err)
}
// 设置请求头
req.Header.Set("User-Agent", getRandomUA())
req.Header.Set("X-Forwarded-For", generateRandomIP())
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("Sec-Fetch-Dest", "empty")
req.Header.Set("Sec-Fetch-Mode", "cors")
req.Header.Set("Sec-Fetch-Site", "same-origin")
var resp *http.Response
var responseBody []byte
// 重试逻辑
for i := 0; i <= p.retries; i++ {
// 发送请求View on GitHub (pinned to beaa561337)