fish2018/pansou · error
创建请求失败
Error message
创建请求失败: %w
What it means
pan666's fetchPage fails when http.NewRequest("GET", apiURL, nil) returns an error while building the search URL (BaseURL + filter[q]/include/page parameters). This only happens with a malformed URL (bad BaseURL, unescaped control characters in the query) — keyword itself is escaped with url.QueryEscape, so the cause is almost always configuration-level.
Solutions
- Print the constructed apiURL and validate it parses (url.Parse) before creating the request
- Check the BaseURL value has scheme https:// and no stray whitespace
- Keep url.QueryEscape(keyword) applied to all user-supplied query components
- Use url.Values.Encode() to build the query string instead of manual fmt.Sprintf
Example fix
// before
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)
// after
q := url.Values{}
q.Set("filter[q]", keyword)
q.Set("include", "mostRelevantPost")
q.Set("page[offset]", fmt.Sprint(offset))
q.Set("page[limit]", fmt.Sprint(PageSize))
req, err := http.NewRequest("GET", BaseURL+"?"+q.Encode(), nil) Defensive patterns
Strategy: validation
Validate before calling
func validateBaseURL(raw string) error {
u, err := url.Parse(strings.TrimSpace(raw))
if err != nil { return err }
if u.Scheme != "https" || u.Host == "" {
return fmt.Errorf("BaseURL must be absolute https URL, got %q", raw)
}
return nil
} Try / catch
if err != nil {
return fmt.Errorf("build request: %w (url was %q)", err, apiURL)
} Prevention
- Validate BaseURL at startup with url.Parse
- Build query strings with url.Values.Encode(), never raw Sprintf
- Trim config-derived URLs of whitespace
- Always QueryEscape user-supplied keyword values
When it happens
Trigger: fetchPage constructs apiURL from BaseURL and calls http.NewRequest; err is non-nil when BaseURL is empty/invalid or contains characters Go's URL parser rejects (spaces, invalid scheme, control chars).
Common situations: BaseURL constant changed to a value with a typo or missing scheme; BaseURL loaded from config containing trailing whitespace/newline; keyword containing characters that survive to break the URL after a refactor removed QueryEscape.
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/ed431768238d7612.
Report an issue: GitHub.
Appendix: source
Thrown at plugin/pan666/pan666.go:185
// 按时间降序排序
sort.Slice(unique, func(i, j int) bool {
return unique[i].Datetime.After(unique[j].Datetime)
})
return unique
}
// fetchPage 获取指定页的搜索结果
func (p *Pan666AsyncPlugin) 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)