fish2018/pansou · error
[ ] 创建token请求失败
Error message
[%s] 创建token请求失败: %w
What it means
getToken wraps the error from http.NewRequestWithContext when building the GET request to the site's token page. The plugin needs a DToken scraped from an HTML page before it can search; if the request object itself cannot be constructed (bad URL, invalid method/ctx combination) the token fetch is aborted and the wrapped error is returned up through searchImpl. This is a pre-flight construction failure, not a network failure.
Solutions
- Print/log the tokenURL value and validate it with url.Parse before calling http.NewRequestWithContext
- Check that BaseURL/tokenURL constants in plugin/xys/xys.go are intact and correctly formatted (https://host/path)
- If the URL is derived from user input, sanitize/escape it (strings.ContainsAny for control chars, url.QueryEscape)
Example fix
// before
req, err := http.NewRequestWithContext(ctx, "GET", tokenURL, nil)
if err != nil {
return "", fmt.Errorf("[%s] 创建token请求失败: %w", p.Name(), err)
}
// after
u, perr := url.Parse(tokenURL)
if perr != nil {
return "", fmt.Errorf("[%s] invalid token URL %q: %w", p.Name(), tokenURL, perr)
}
req, err := http.NewRequestWithContext(ctx, "GET", u.String(), nil)
if err != nil {
return "", fmt.Errorf("[%s] 创建token请求失败: %w", p.Name(), err)
} Defensive patterns
Strategy: validation
Validate before calling
u, err := url.Parse(tokenURL)
if err != nil || u.Scheme == "" || u.Host == "" {
return fmt.Errorf("invalid token URL: %v", err)
} Try / catch
if err != nil {
var ue *url.Error
if errors.As(err, &ue) {
log.Printf("bad token URL %q: %v", ue.URL, ue.Err)
}
return fallbackSearch()
} Prevention
- Always validate URLs composed from constants/config with url.Parse before use
- Never interpolate unsanitized user input into URLs; use url.QueryEscape
- Pin BaseURL/tokenURL in tests so accidental edits fail CI
When it happens
Trigger: http.NewRequestWithContext(ctx, "GET", tokenURL, nil) returns a non-nil err — in practice a malformed or unparseable tokenURL (e.g. control characters, unparseable scheme) since method/ctx are constants here.
Common situations: BaseURL or token URL constant corrupted by an edit or config substitution; URL built with unescaped user input containing newlines/control chars; Go stdlib rejecting an invalid URL 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/53818b861b718583.
Report an issue: GitHub.
Appendix: source
Thrown at plugin/xys/xys.go:149
if p.debugMode {
log.Printf("[XYS] 使用缓存的token")
}
return tokenCache.Token, nil
}
}
}
// 构建请求URL
tokenURL := fmt.Sprintf("%s%s?wd=%s&mode=undefined&stype=undefined",
BaseURL, TokenPath, url.QueryEscape(keyword))
// 创建带超时的上下文
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
req, err := http.NewRequestWithContext(ctx, "GET", tokenURL, nil)
if err != nil {
return "", fmt.Errorf("[%s] 创建token请求失败: %w", p.Name(), err)
}
// 设置完整的请求头
req.Header.Set("User-Agent", UserAgent)
req.Header.Set("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8")
req.Header.Set("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8")
req.Header.Set("Connection", "keep-alive")
req.Header.Set("Upgrade-Insecure-Requests", "1")
req.Header.Set("Cache-Control", "max-age=0")
req.Header.Set("Referer", BaseURL+"/")
resp, err := p.doRequestWithRetry(req, client)
if err != nil {
return "", fmt.Errorf("[%s] token请求失败: %w", p.Name(), err)
}
defer resp.Body.Close()
if resp.StatusCode != 200 {View on GitHub (pinned to beaa561337)