如何优雅地重复读取HTTP响应体
背景介绍 在Go语言中处理HTTP请求时,我们经常需要多次读取响应体(Response Body)的内容。然而,默认情况下Response Body只能被读取一次,这是因为它实现了io.ReadCloser接口,读取完毕后数据就会被消费掉。本文将介绍一个优雅的解决方案。
问题描述 假设我们有以下场景:
需要在日志中记录API的响应内容 需要对响应内容进行多次处理 需要在中间件中查看响应内容,同时不影响后续处理 解决方案 我们可以使用io.TeeReader来实现响应体的复制,这样就能多次读取相同的内容。以下是具体实现:
package main import ( "bytes" "fmt" "io" "net/http" ) func DupReadCloser(reader io.ReadCloser) (io.ReadCloser, io.ReadCloser) { var buf bytes.Buffer tee := io.TeeReader(reader, &buf) return io.NopCloser(tee), io.NopCloser(&buf) } func DupResponseBody(resp *http.Response) ([]byte, error) { var buf io.ReadCloser resp.Body, buf = DupReadCloser(resp.Body) data, err := io.ReadAll(resp.Body) if err != nil { return nil, err } resp.Body = buf return data, nil } 代码解析 DupReadCloser函数:接收一个io.……