{"record":{"id":"f09805e284d979e8","repo":"fish2018/pansou","slug":"s-w-f09805","errorCode":null,"errorMessage":"[%s] 读取响应失败: %w","messagePattern":"\\[(.+?)\\] 读取响应失败: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"plugin/wanou/wanou.go","lineNumber":149,"sourceCode":"\t// 设置请求头\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\", \"application/json, text/plain, */*\")\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(\"Referer\", \"https://woog.nxog.eu.org/\")\n\treq.Header.Set(\"Cache-Control\", \"no-cache\")\n\t\n\t// 发送请求\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\t\n\t// 解析JSON响应\n\tbody, err := io.ReadAll(resp.Body)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"[%s] 读取响应失败: %w\", p.Name(), err)\n\t}\n\t\n\tvar apiResponse WanouAPIResponse\n\tif err := json.Unmarshal(body, &apiResponse); err != nil {\n\t\treturn nil, fmt.Errorf(\"[%s] 解析JSON响应失败: %w\", p.Name(), err)\n\t}\n\t\n\t// 检查API响应状态\n\tif apiResponse.Code != 1 {\n\t\treturn nil, fmt.Errorf(\"[%s] API返回错误: %s\", p.Name(), apiResponse.Msg)\n\t}\n\t\n\t// 解析搜索结果\n\tvar results []model.SearchResult\n\tfor _, item := range apiResponse.List {\n\t\tif result := p.parseAPIItem(item); result.Title != \"\" {\n\t\t\tresults = append(results, result)\n\t\t}","sourceCodeStart":131,"sourceCodeEnd":167,"githubUrl":"https://github.com/fish2018/pansou/blob/beaa56133755a548ebc51b090b3816e2ae044aa6/plugin/wanou/wanou.go#L131-L167","documentation":"After a successful HTTP response, searchImpl reads the entire body with io.ReadAll. If reading fails (connection reset mid-response, context timeout during body transfer, truncated response), it wraps the error as '读取响应失败' (failed to read response).","triggerScenarios":"The server closes the connection before the body completes; the request context times out while streaming the body; a proxy drops the connection; extremely large/aborted responses.","commonSituations":"Unstable network to an overseas mirror; server-side idle timeouts cutting long responses; rate limiting that closes connections; keep-alive connections reused after the server timed them out.","solutions":["Retry the request (doRequestWithRetry may already have succeeded but the body read is outside it — move body reading inside the retry)","Increase the context timeout so the body read is not cut off","Disable keep-alive or set DisableKeepAlives to avoid stale reused connections","Check whether a proxy or LB is truncating responses"],"exampleFix":"// before\nresp, err := p.doRequestWithRetry(req, client)\nif err != nil { return nil, ... }\ndefer resp.Body.Close()\nbody, err := io.ReadAll(resp.Body)\nif err != nil { return nil, fmt.Errorf(\"[%s] 读取响应失败: %w\", p.Name(), err) }\n// after\nbody, err := p.readBodyWithRetry(req, client) // body read inside retry loop\nif err != nil {\n    return nil, fmt.Errorf(\"[%s] 读取响应失败: %w\", p.Name(), err)\n}","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"body, err := io.ReadAll(resp.Body)\nif err != nil {\n    if errors.Is(err, context.DeadlineExceeded) || errors.Is(err, io.ErrUnexpectedEOF) {\n        return retrySearch(query) // transient truncation — retry\n    }\n    return nil, err\n}","preventionTips":["Keep the request context alive long enough to read the full body","Disable keep-alive if stale connections cause resets","Read the body inside the retry loop so truncated reads are retried","Set reasonable client timeouts (dial/response/header)"],"tags":["io","network","http-body"],"backgroundTag":"file-read-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"}