{"record":{"id":"0d4e1b34155962ad","repo":"fish2018/pansou","slug":"gzip-reader-w-0d4e1b","errorCode":null,"errorMessage":"创建gzip reader失败: %w","messagePattern":"创建gzip reader失败: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"plugin/libvio/libvio.go","lineNumber":199,"sourceCode":"\n\treturn filteredResults, nil\n}\n\n// getResponseReader 获取响应读取器（处理gzip压缩）\nfunc (p *LibvioPlugin) getResponseReader(resp *http.Response) (io.Reader, error) {\n\tvar reader io.Reader = resp.Body\n\n\t// 检查Content-Encoding\n\tcontentEncoding := resp.Header.Get(\"Content-Encoding\")\n\tif p.debugMode {\n\t\tlog.Printf(\"[Libvio] Content-Encoding: %s\", contentEncoding)\n\t}\n\n\t// 如果是gzip压缩，手动解压\n\tif contentEncoding == \"gzip\" {\n\t\tgzReader, err := gzip.NewReader(resp.Body)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"创建gzip reader失败: %w\", err)\n\t\t}\n\t\t// 注意：不要在这里关闭gzReader，它需要在外部使用\n\t\treader = gzReader\n\t}\n\n\treturn reader, nil\n}\n\n// extractSearchResults 从HTML中提取搜索结果\nfunc (p *LibvioPlugin) extractSearchResults(doc *goquery.Document, keyword string) []model.SearchResult {\n\tvar results []model.SearchResult\n\n\t// 选择所有搜索结果项\n\tdoc.Find(\"ul.stui-vodlist li\").Each(func(i int, s *goquery.Selection) {\n\t\t// 提取标题和详情页链接\n\t\ttitleElem := s.Find(\".stui-vodlist__detail h4 a\")\n\t\ttitle := strings.TrimSpace(titleElem.Text())\n\t\tif title == \"\" {","sourceCodeStart":181,"sourceCodeEnd":217,"githubUrl":"https://github.com/fish2018/pansou/blob/beaa56133755a548ebc51b090b3816e2ae044aa6/plugin/libvio/libvio.go#L181-L217","documentation":"getResponseReader detected Content-Encoding: gzip on the HTTP response but gzip.NewReader failed to wrap resp.Body. gzip.NewReader fails on the first bytes if the body is not actually a valid gzip stream. This error propagates to all callers: searchImpl, fetchDetailPageLinks, and fetchPanLink.","triggerScenarios":"Server sent Content-Encoding: gzip header but the body is not gzip (e.g. a proxy/WAF already decompressed it, body is an error page, or an encoding mismatch like brotli mislabeled as gzip).","commonSituations":"Reverse proxy or CDN strips/alters encoding; site misconfigures Content-Encoding; middleware double-decompresses; server returns compressed error page with wrong header.","solutions":["Log the first bytes of resp.Body (after Peek) to verify whether the stream is really gzip","Handle double-decompression: sniff the body magic (0x1f 0x8b) instead of trusting the header, and pass through if not gzip","Disable automatic transparent decompression that conflicts with manual gzip handling (avoid custom Transport DisableCompression mismatches)","Retry the request once, since transient proxies can send mismatched bodies","Check brotli/deflate: if Content-Encoding is br or deflate, add appropriate decoders instead of falling through"],"exampleFix":"// before\nif contentEncoding == \"gzip\" {\n    gzReader, err := gzip.NewReader(resp.Body)\n    if err != nil {\n        return nil, fmt.Errorf(\"创建gzip reader失败: %w\", err)\n    }\n    reader = gzReader\n}\n// after\nif contentEncoding == \"gzip\" {\n    br := bufio.NewReader(resp.Body)\n    magic, _ := br.Peek(2)\n    if len(magic) == 2 && magic[0] == 0x1f && magic[1] == 0x8b {\n        gzReader, err := gzip.NewReader(br)\n        if err != nil {\n            return nil, fmt.Errorf(\"创建gzip reader失败: %w\", err)\n        }\n        reader = gzReader\n    } else {\n        reader = br // server lied about gzip; use raw body\n    }\n}","handlingStrategy":"validation","validationCode":"// Validate gzip magic bytes before wrapping\nbr := bufio.NewReader(resp.Body)\nmagic, _ := br.Peek(2)\nif resp.Header.Get(\"Content-Encoding\") == \"gzip\" && !(len(magic) == 2 && magic[0] == 0x1f && magic[1] == 0x8b) {\n    return fmt.Errorf(\"声明gzip但内容非法: % x\", magic)\n}","typeGuard":"func isGzipStream(r io.Reader) (bool, io.Reader) {\n    br := bufio.NewReader(r)\n    magic, _ := br.Peek(2)\n    return len(magic) == 2 && magic[0] == 0x1f && magic[1] == 0x8b, br\n}","tryCatchPattern":"doc, err := fetchAndParse(url)\nif err != nil && strings.Contains(err.Error(), \"创建gzip reader失败\") {\n    // encoding mismatch: retry once with a fresh client, or sniff-and-decode manually\n    doc, err = fetchAndParseWithSniffing(url)\n}","preventionTips":["Sniff gzip magic bytes instead of trusting Content-Encoding","Don't stack a decompressing Transport with manual gzip.NewReader","Add brotli/deflate support so unknown encodings don't fall through","Test behind proxies/CDNs that rewrite encoding headers"],"tags":["gzip","http","compression","network"],"backgroundTag":"invalid-gzip-stream","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"}