fish2018/pansou · error
[ ] 创建请求失败
Error message
[%s] 创建请求失败: %w
What it means
http.NewRequestWithContext failed while building the POST request to the API URL. This occurs before any network I/O and almost always means the URL failed to parse or the body/io.Reader itself errored.
Solutions
- Print/validate apiURL before constructing the request (url.Parse the constant at init)
- Check the wrapped error's message for 'parse ...: invalid ...' hints
- Fix the configuration or constant supplying apiURL
Example fix
// before
req, err := http.NewRequestWithContext(ctx, "POST", apiURL, bytes.NewBuffer(jsonData))
// after
if _, perr := url.Parse(apiURL); perr != nil {
return nil, fmt.Errorf("无效的API地址 %q: %w", apiURL, perr)
}
req, err := http.NewRequestWithContext(ctx, "POST", apiURL, bytes.NewBuffer(jsonData)) Defensive patterns
Strategy: validation
Validate before calling
u, err := url.Parse(apiURL)
if err != nil || u.Scheme == "" || u.Host == "" {
return fmt.Errorf("无效的API地址: %q", apiURL)
} Try / catch
req, err := http.NewRequestWithContext(ctx, "POST", apiURL, bytes.NewBuffer(jsonData))
if err != nil {
return nil, fmt.Errorf("[%s] 创建请求失败: %w", pluginName, err)
} Prevention
- Validate apiURL at plugin init with url.Parse
- Never interpolate raw user/config strings into URLs without escaping
- Pin the API URL as a validated constant
When it happens
Trigger: apiURL is malformed (bad scheme, spaces, control characters) or the request body reader returns an error when NewRequest reads it into memory.
Common situations: apiURL built from an empty or misconfigured base URL; configuration containing whitespace or invalid characters interpolated into the URL; constant leaked into apiURL.
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/d861fb664d7ddbdc.
Report an issue: GitHub.
Appendix: source
Thrown at plugin/xdyh/xdyh.go:136
MaxWorkers: 10, // API默认并发数
SaveToFile: false,
SplitLinks: true,
}
// 3. JSON序列化
jsonData, err := json.Marshal(requestBody)
if err != nil {
return nil, fmt.Errorf("[%s] JSON序列化失败: %w", pluginName, err)
}
// 4. 创建带超时的上下文
ctx, cancel := context.WithTimeout(context.Background(), DefaultTimeout)
defer cancel()
// 5. 创建请求
req, err := http.NewRequestWithContext(ctx, "POST", apiURL, bytes.NewBuffer(jsonData))
if err != nil {
return nil, fmt.Errorf("[%s] 创建请求失败: %w", pluginName, err)
}
// 6. 设置请求头
p.setRequestHeaders(req)
// 7. 发送请求
resp, err := p.doRequestWithRetry(req, client)
if err != nil {
return nil, fmt.Errorf("[%s] 搜索请求失败: %w", pluginName, err)
}
defer resp.Body.Close()
// 8. 检查状态码
if resp.StatusCode != 200 {
return nil, fmt.Errorf("[%s] 请求返回状态码: %d", pluginName, resp.StatusCode)
}
// 9. 读取响应体View on GitHub (pinned to beaa561337)