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

  1. 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.
  2. Unwrap the error to distinguish reader-setup failure (encoding) from io.ReadAll failure (transport); retry the request for the latter.
  3. Check the response Content-Type/charset and ensure the reader decodes non-UTF8 charsets correctly.
  4. Increase the request timeout if large bodies are cut off mid-read.
  5. 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

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)