fish2018/pansou · error
解析搜索地址失败
Error message
解析搜索地址失败: %w
What it means
Wraps an error from url.Parse when constructing the search endpoint URL "%s/_serverFn/%s" from the plugin's baseURL and the server function ID. Indicates the assembled endpoint is not a valid URL — almost always because baseURL is misconfigured rather than a bad functionID (which is a plain hex hash).
Solutions
- Print/inspect the exact endpoint string that failed to parse
- Validate the configured baseURL: it must include scheme (https://) and contain no spaces or stray '%' escapes
- Run url.Parse on the baseURL alone to isolate which part is invalid
- Percent-encode or strip invalid characters before composing the endpoint
Example fix
// before
endpoint := fmt.Sprintf("%s/_serverFn/%s", strings.TrimRight(p.baseURL, "/"), functionID)
parsedEndpoint, err := url.Parse(endpoint)
// after: validate the base up front
if _, err := url.Parse(p.baseURL); err != nil {
return nil, fmt.Errorf("invalid baseURL %q: %w", p.baseURL, err)
}
endpoint := fmt.Sprintf("%s/_serverFn/%s", strings.TrimRight(p.baseURL, "/"), functionID)
parsedEndpoint, err := url.Parse(endpoint) Defensive patterns
Strategy: validation
Validate before calling
func validateBaseURL(raw string) error {
u, err := url.Parse(raw)
if err != nil { return err }
if u.Scheme == "" || u.Host == "" { return fmt.Errorf("baseURL %q needs scheme and host", raw) }
return nil
}
if err := validateBaseURL(cfg.XiaokupanBaseURL); err != nil { /* reject config */ } Type guard
func isUsableURL(u *url.URL) bool { return u != nil && u.Scheme != "" && u.Host != "" } Try / catch
if err != nil {
var urlErr *url.Error
if errors.As(err, &urlErr) {
log.Printf("malformed endpoint %q: %v", endpoint, urlErr)
}
return err
} Prevention
- Always configure baseURL as an absolute URL with https:// scheme
- Trim and validate config values before injecting them into URL templates
- Escape/encode any dynamic segment before string-formatting into a URL
When it happens
Trigger: url.Parse fails on baseURL+"/_serverFn/"+functionID — e.g. baseURL contains characters illegal in a URL (spaces, unescaped control chars, stray percent signs like 'https://xiaokupan.com%'), or a custom baseURL was set to a malformed value.
Common situations: Operator misconfigures the plugin's base URL (typo, extra protocol, unescaped characters); environment substitution injects whitespace into the URL; copy-pasted URL with trailing invisible characters.
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/e80afbd5c525b130.
Report an issue: GitHub.
Appendix: source
Thrown at plugin/xiaokupan/xiaokupan.go:118
}
results, err = p.searchWithFunctionID(client, keyword, refreshedID)
}
if err != nil {
return nil, fmt.Errorf("[%s] 搜索失败: %w", p.Name(), err)
}
return plugin.FilterResultsByKeyword(results, keyword), nil
}
func (p *XiaokupanPlugin) searchWithFunctionID(client *http.Client, keyword, functionID string) ([]model.SearchResult, error) {
payload, err := buildSearchPayload(keyword)
if err != nil {
return nil, fmt.Errorf("构造搜索参数失败: %w", err)
}
endpoint := fmt.Sprintf("%s/_serverFn/%s", strings.TrimRight(p.baseURL, "/"), functionID)
parsedEndpoint, err := url.Parse(endpoint)
if err != nil {
return nil, fmt.Errorf("解析搜索地址失败: %w", err)
}
query := parsedEndpoint.Query()
query.Set("payload", string(payload))
parsedEndpoint.RawQuery = query.Encode()
ctx, cancel := context.WithTimeout(context.Background(), requestTimeout)
defer cancel()
req, err := http.NewRequestWithContext(ctx, http.MethodGet, parsedEndpoint.String(), nil)
if err != nil {
return nil, fmt.Errorf("创建搜索请求失败: %w", err)
}
p.setSearchHeaders(req, keyword)
body, err := doLimitedRequest(client, req, maxSearchResponseSize)
if err != nil {
return nil, err
}View on GitHub (pinned to beaa561337)