{"record":{"id":"c7bd876263f795da","repo":"fish2018/pansou","slug":"s-w-c7bd87","errorCode":null,"errorMessage":"[%s] 搜索请求失败: %w","messagePattern":"\\[(.+?)\\] 搜索请求失败: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"plugin/alupan/alupan.go","lineNumber":133,"sourceCode":"func (p *AlupanPlugin) searchImpl(client *http.Client, keyword string, ext map[string]interface{}) ([]model.SearchResult, error) {\n\tif p.client != nil {\n\t\tclient = p.client\n\t}\n\n\tsearchURL := fmt.Sprintf(\"https://www.aliupan.com/?s=%s\", url.QueryEscape(keyword))\n\tctx, cancel := context.WithTimeout(context.Background(), searchTimeout)\n\tdefer cancel()\n\n\treq, err := http.NewRequestWithContext(ctx, http.MethodGet, searchURL, nil)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"[%s] 创建请求失败: %w\", p.Name(), err)\n\t}\n\n\tsetCommonHeaders(req, \"https://www.aliupan.com/\")\n\n\tresp, err := p.doRequestWithRetry(req, client, searchMaxRetries)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"[%s] 搜索请求失败: %w\", p.Name(), err)\n\t}\n\tdefer resp.Body.Close()\n\n\tif resp.StatusCode != http.StatusOK {\n\t\treturn nil, fmt.Errorf(\"[%s] 搜索返回状态码: %d\", p.Name(), resp.StatusCode)\n\t}\n\n\tdoc, err := goquery.NewDocumentFromReader(resp.Body)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"[%s] 解析搜索页面失败: %w\", p.Name(), err)\n\t}\n\n\tvar (\n\t\tresults []model.SearchResult\n\t\twg      sync.WaitGroup\n\t\tmu      sync.Mutex\n\t\tsem     = make(chan struct{}, maxConcurrency)\n\t)","sourceCodeStart":115,"sourceCodeEnd":151,"githubUrl":"https://github.com/fish2018/pansou/blob/beaa56133755a548ebc51b090b3816e2ae044aa6/plugin/alupan/alupan.go#L115-L151","documentation":"searchImpl wraps any error returned by doRequestWithRetry for the alupan search request. It means the HTTP GET to www.aliupan.com failed on every retry attempt — network-level failure or timeout — before any response body could be processed. The underlying cause is preserved via %w.","triggerScenarios":"doRequestWithRetry exhausts searchMaxRetries (3) because of DNS failure, connection refused/reset, TLS handshake timeout, or the 12-second searchTimeout context/client deadline expiring on each attempt.","commonSituations":"aliupan.com is down, geo-blocked, or rate-limiting the host; the deployment environment has no internet egress; a corporate proxy intercepts HTTPS; the 12s timeout is too short on a slow connection; site started requiring cookies/JS challenge (Cloudflare).","solutions":["Inspect the wrapped error (errors.Is for context.DeadlineExceeded, *net.OpError, etc.) to identify the root cause.","Test reachability: curl -v 'https://www.aliupan.com/?s=test' from the deployment host; check proxy env vars.","Increase searchTimeout (currently 12s) or searchMaxRetries (3) if failures are transient/slow-network.","Check for anti-bot/Cloudflare challenges; add appropriate headers or cookies in setCommonHeaders if the site began blocking.","Fall back gracefully — skip this plugin and aggregate results from other plugins when it fails."],"exampleFix":"// before\nresp, err := p.doRequestWithRetry(req, client, searchMaxRetries)\n// after\nresp, err := p.doRequestWithRetry(req, client, searchMaxRetries)\nif errors.Is(err, context.DeadlineExceeded) {\n    // bump searchTimeout or retry with a fresh context\n}","handlingStrategy":"retry","validationCode":"// Quick pre-flight before running the full search\nctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)\ndefer cancel()\nreq, _ := http.NewRequestWithContext(ctx, http.MethodHead, \"https://www.aliupan.com/\", nil)\nif _, err := http.DefaultClient.Do(req); err != nil {\n    log.Printf(\"aliupan unreachable: %v\", err) // skip plugin or alert\n}","typeGuard":null,"tryCatchPattern":"// Go: classify the wrapped transport error and fall back\nif err != nil {\n    switch {\n    case errors.Is(err, context.DeadlineExceeded):\n        log.Println(\"aliupan: request timed out after retries\")\n    case errors.Is(err, syscall.ECONNREFUSED):\n        log.Println(\"aliupan: connection refused\")\n    default:\n        log.Printf(\"aliupan: request failed: %v\", err)\n    }\n    // continue with other plugins' results\n}","preventionTips":["Keep searchTimeout and retry counts sized to the site's real latency.","Test egress (curl) from the deployment environment, including proxy settings.","Update User-Agent/Referer headers when the site tightens bot protection.","Degrade gracefully: aggregate other plugins' results instead of failing the whole search."],"tags":["network","http","timeout","retry","go"],"backgroundTag":"http-request-failed","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"}