{"record":{"id":"8ec6681a7705ea12","repo":"fish2018/pansou","slug":"s-w-8ec668","errorCode":null,"errorMessage":"[%s] 创建搜索请求失败: %w","messagePattern":"\\[(.+?)\\] 创建搜索请求失败: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"plugin/javdb/javdb.go","lineNumber":177,"sourceCode":"\t\t// 显示重试配置信息\n\t\tif MaxRetryOnRateLimit > 0 {\n\t\t\tlog.Printf(\"[JAVDB] 429重试配置: 最大%d次，延迟%d-%d秒\", MaxRetryOnRateLimit, MinRetryDelay, MaxRetryDelay)\n\t\t} else {\n\t\t\tlog.Printf(\"[JAVDB] 429重试配置: 禁用重试\")\n\t\t}\n\t\t// 如果之前有限流，显示统计信息\n\t\tif count := atomic.LoadInt32(&p.rateLimitCount); count > 0 {\n\t\t\tlog.Printf(\"[JAVDB] 历史429限流次数: %d\", count)\n\t\t}\n\t}\n\n\t// 创建带超时的上下文\n\tctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)\n\tdefer cancel()\n\n\treq, err := http.NewRequestWithContext(ctx, \"GET\", searchURL, nil)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"[%s] 创建搜索请求失败: %w\", p.Name(), err), false\n\t}\n\n\t// 设置完整的请求头\n\treq.Header.Set(\"User-Agent\", UserAgent)\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\", BaseURL+\"/\")\n\n\tif p.debugMode {\n\t\tlog.Printf(\"[JAVDB] 发送搜索请求...\")\n\t}\n\n\tresp, err := client.Do(req)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"[%s] 搜索请求失败: %w\", p.Name(), err), false","sourceCodeStart":159,"sourceCodeEnd":195,"githubUrl":"https://github.com/fish2018/pansou/blob/beaa56133755a548ebc51b090b3816e2ae044aa6/plugin/javdb/javdb.go#L159-L195","documentation":"executeSearchWithRateLimit returns '[javdb] 创建搜索请求失败: %w' (failed to create search request) when http.NewRequestWithContext cannot construct the GET request for the search URL. In Go this only happens for an invalid URL/method, and the plugin propagates the wrapped stdlib error.","triggerScenarios":"The constructed searchURL fails http.NewRequestWithContext parsing — e.g. the URL contains unescaped characters (control chars, spaces, invalid percent-encoding) because the raw keyword was interpolated without url.QueryEscape.","commonSituations":"User-submitted search keywords containing spaces, '#', '%', or newlines concatenated directly into the URL; config override producing a malformed base URL.","solutions":["Escape the keyword with url.QueryEscape before building searchURL","Validate/normalize the base search URL configured for the plugin","Log the exact searchURL on failure to spot malformed characters","Reject or sanitize keywords containing control characters before searching"],"exampleFix":"// before\nsearchURL := baseURL + \"/search?q=\" + keyword\n// after\nsearchURL := baseURL + \"/search?q=\" + url.QueryEscape(keyword)","handlingStrategy":"validation","validationCode":"// Go: validate the URL is parseable before issuing the request\nu, err := url.Parse(searchURL)\nif err != nil || u.Scheme == \"\" || u.Host == \"\" {\n    return fmt.Errorf(\"invalid search URL: %q\", searchURL)\n}","typeGuard":"func isValidURL(s string) bool {\n    u, err := url.Parse(s)\n    return err == nil && u.Scheme != \"\" && u.Host != \"\"\n}","tryCatchPattern":"req, err := http.NewRequestWithContext(ctx, \"GET\", searchURL, nil)\nif err != nil {\n    return nil, fmt.Errorf(\"bad search url %q: %w\", searchURL, err), false\n}","preventionTips":["Always url.QueryEscape user-supplied keywords","Sanitize keywords (strip control characters) before interpolation","Validate configured base URLs at plugin startup","Log the offending URL in the error message for fast diagnosis"],"tags":["url","encoding","go","http"],"backgroundTag":"invalid-url","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"}