{"record":{"id":"d8de7aae33cfbcac","repo":"fish2018/pansou","slug":"s-w-d8de7a","errorCode":null,"errorMessage":"[%s] 创建请求失败: %w","messagePattern":"\\[(.+?)\\] 创建请求失败: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"plugin/shandian/shandian.go","lineNumber":184,"sourceCode":"\n\t// 8. 异步获取详情页信息\n\tenhancedResults := p.enhanceWithDetails(client, results, selectedBase)\n\n\t// 9. 关键词过滤\n\treturn plugin.FilterResultsByKeyword(enhancedResults, keyword), nil\n}\n\nfunc (p *ShandianAsyncPlugin) searchAtBase(client *http.Client, keyword, baseURL string) ([]model.SearchResult, error) {\n\tsearchURL := fmt.Sprintf(\"%s/index.php/vod/search/wd/%s.html\", strings.TrimRight(baseURL, \"/\"), url.QueryEscape(keyword))\n\n\t// 2. 创建带超时的上下文\n\tctx, cancel := context.WithTimeout(context.Background(), DefaultTimeout)\n\tdefer cancel()\n\n\t// 3. 创建请求\n\treq, err := http.NewRequestWithContext(ctx, \"GET\", searchURL, nil)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"[%s] 创建请求失败: %w\", p.Name(), err)\n\t}\n\n\t// 4. 设置完整的请求头（避免反爬虫）\n\treq.Header.Set(\"User-Agent\", \"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36\")\n\treq.Header.Set(\"Accept\", \"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8\")\n\treq.Header.Set(\"Accept-Language\", \"zh-CN,zh;q=0.9,en;q=0.8\")\n\treq.Header.Set(\"Connection\", \"keep-alive\")\n\treq.Header.Set(\"Upgrade-Insecure-Requests\", \"1\")\n\treq.Header.Set(\"Cache-Control\", \"max-age=0\")\n\treq.Header.Set(\"Referer\", strings.TrimRight(baseURL, \"/\")+\"/\")\n\n\t// 5. 发送请求（带重试机制）\n\tresp, err := p.doRequestWithRetry(req, client)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"[%s] 搜索请求失败: %w\", p.Name(), err)\n\t}\n\tdefer resp.Body.Close()\n","sourceCodeStart":166,"sourceCodeEnd":202,"githubUrl":"https://github.com/fish2018/pansou/blob/beaa56133755a548ebc51b090b3816e2ae044aa6/plugin/shandian/shandian.go#L166-L202","documentation":"searchAtBase builds a GET http.Request via http.NewRequestWithContext for the mirror's search URL. If the URL is malformed (unparseable), NewRequestWithContext fails and the error is wrapped as 创建请求失败. In Go this almost exclusively means the URL string is invalid; the request was never sent.","triggerScenarios":"baseURL configured with an invalid scheme (missing http:// or https://), containing spaces/control characters, or keyword escaping producing an unparseable URL — http.NewRequestWithContext returns *url.Error which is wrapped here.","commonSituations":"A mirror entry in config entered as \"mysite.com\" without a scheme; trailing whitespace or newline in the configured URL; empty baseURL combined with the path format producing \"/index.php/...\".","solutions":["Normalize each sourceURL before use: ensure it starts with http:// or https:// (prepend https:// if scheme missing).","strings.TrimSpace each configured base URL and reject/skip empty entries.","Validate URLs with url.Parse at config-load time and log invalid mirrors instead of failing at search time.","Log the composed searchURL on failure to see the exact malformed value."],"exampleFix":"// before\nsearchURL := fmt.Sprintf(\"%s/index.php/vod/search/wd/%s.html\", strings.TrimRight(baseURL, \"/\"), url.QueryEscape(keyword))\n// after\nbase := strings.TrimSpace(baseURL)\nif !strings.HasPrefix(base, \"http://\") && !strings.HasPrefix(base, \"https://\") {\n    base = \"https://\" + base\n}\nsearchURL := fmt.Sprintf(\"%s/index.php/vod/search/wd/%s.html\", strings.TrimRight(base, \"/\"), url.QueryEscape(keyword))","handlingStrategy":"validation","validationCode":"u := strings.TrimSpace(baseURL)\nif u != \"\" && !strings.Contains(u, \"://\") {\n    u = \"https://\" + u\n}\nif _, err := url.Parse(strings.TrimRight(u, \"/\") + \"/index.php/vod/search/wd/test.html\"); err != nil {\n    return fmt.Errorf(\"invalid search base URL %q: %w\", u, err)\n}","typeGuard":"func isValidHTTPURL(s string) bool {\n    u, err := url.Parse(s)\n    return err == nil && (u.Scheme == \"http\" || u.Scheme == \"https\") && u.Host != \"\"\n}","tryCatchPattern":null,"preventionTips":["Validate mirror URLs with url.Parse at config-load time.","Always include an explicit http(s) scheme in configured base URLs.","Trim whitespace/newlines from configuration values.","Log the fully composed URL when request creation fails."],"tags":["http","url","validation","go"],"backgroundTag":"invalid-url-format","analyzedSha":"beaa56133755a548ebc51b090b3816e2ae044aa6","analyzedAt":"2026-09-07T00:31:18.025Z","contentChangedAt":"2026-09-07T00:31:18.025Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}