fish2018/pansou · error
读取响应体失败
Error message
读取响应体失败: %w
What it means
When the xb6v search POST returns no Location header, searchImpl falls back to parsing the response body for a redirect. It obtains a reader via p.getResponseReader(resp) (which likely handles gzip/charset) and wraps any failure of that reader setup — or of the subsequent io.ReadAll — as this error. It means the redirect-bearing body could not be obtained or decoded.
Solutions
- Log resp.Header.Get("Content-Encoding") when this fires; extend getResponseReader to handle the encoding (e.g. brotli) or send 'Accept-Encoding: gzip' explicitly so the server uses a supported one.
- Unwrap the error to distinguish reader-setup failure (encoding) from io.ReadAll failure (transport); retry the request for the latter.
- Check the response Content-Type/charset and ensure the reader decodes non-UTF8 charsets correctly.
- Increase the request timeout if large bodies are cut off mid-read.
- Prefer forcing a supported encoding on the request so the fallback body parse is reliable.
Example fix
// before
bodyReader, err := p.getResponseReader(resp)
if err != nil {
return nil, fmt.Errorf("读取响应体失败: %w", err)
}
// after
bodyReader, err := p.getResponseReader(resp)
if err != nil {
return nil, fmt.Errorf("读取响应体失败 (Content-Encoding=%q): %w", resp.Header.Get("Content-Encoding"), err)
} Defensive patterns
Strategy: try-catch
Validate before calling
enc := resp.Header.Get("Content-Encoding")
if enc != "" && enc != "gzip" && enc != "deflate" && enc != "identity" {
return fmt.Errorf("unsupported Content-Encoding: %s", enc)
} Try / catch
bodyReader, err := p.getResponseReader(resp)
if err != nil {
return nil, fmt.Errorf("读取响应体失败 (encoding=%q): %w", resp.Header.Get("Content-Encoding"), err)
} Prevention
- Send an explicit supported Accept-Encoding header on requests
- Extend the response reader for new encodings (br, zstd) before the site adopts them
- Retry transport-level read errors; treat encoding errors as code fixes
- Verify charset handling for non-UTF8 responses
When it happens
Trigger: Either p.getResponseReader(resp) errors (unhandled Content-Encoding/charset, e.g. an unexpected gzip/brotli payload) or io.ReadAll(bodyReader) fails (connection reset mid-body, timeout during transfer, corrupt chunked encoding). Only reached when the search POST returned 200/3xx without a Location header.
Common situations: The site starts serving brotli (br) or zstd encoding the reader does not support; the server truncates the response mid-transfer; the response is HTML stating an error but encoded unusually; flaky network to the target.
Understand the failure class
Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.
Related errors
AI-assisted analysis of fish2018/pansou@beaa561337 (2026-09-07).
Data as JSON: /api/errors/17eebaef9da3d0fe.
Report an issue: GitHub.
Appendix: source
Thrown at plugin/xb6v/xb6v.go:205
log.Printf("[Xb6v] POST响应状态码: %d", resp.StatusCode)
}
// 获取重定向的location
location := resp.Header.Get("Location")
if p.debugMode {
log.Printf("[Xb6v] Location头: '%s'", location)
}
// 如果没有Location头,可能需要从响应体中解析
if location == "" {
if p.debugMode {
log.Printf("[Xb6v] 未找到Location头,尝试解析响应体")
}
// 读取响应体看看是否包含重定向信息
bodyReader, err := p.getResponseReader(resp)
if err != nil {
return nil, fmt.Errorf("读取响应体失败: %w", err)
}
bodyBytes, err := io.ReadAll(bodyReader)
if err != nil {
return nil, fmt.Errorf("读取响应体失败: %w", err)
}
bodyStr := string(bodyBytes)
if p.debugMode {
log.Printf("[Xb6v] 响应体长度: %d", len(bodyStr))
// 只打印前500个字符避免日志过长
if len(bodyStr) > 500 {
log.Printf("[Xb6v] 响应体前500字符: %s", bodyStr[:500])
} else {
log.Printf("[Xb6v] 响应体内容: %s", bodyStr)
}
}
View on GitHub (pinned to beaa561337)