记录响应主体时Golang DumpResponse gzip问题(reverseproxy)

记录响应主体时Golang DumpResponse gzip问题(reverseproxy),go,gzip,reverse-proxy,Go,Gzip,Reverse Proxy,我在main.go中创建了一个简单的反向代理,如下所示: reverseproxy := httputil.NewSingleHostReverseProxy("https://someurl/someuri") 这工作正常,但是,我想记录从服务器返回的响应。我也可以使用golang推荐的标准往返方法中的以下代码来实现这一点: response, err := http.DefaultTransport.RoundTrip(request) dumpresp, err := httputil.

我在main.go中创建了一个简单的反向代理,如下所示:

reverseproxy := httputil.NewSingleHostReverseProxy("https://someurl/someuri")
这工作正常,但是,我想记录从服务器返回的响应。我也可以使用golang推荐的标准往返方法中的以下代码来实现这一点:

response, err := http.DefaultTransport.RoundTrip(request)
dumpresp, err := httputil.DumpResponse(response, true)

if err != nil {
    return nil, err
}
log.Printf("%s", dumpresp)
除了响应之外,上述所有功能都可以正常工作,当内容编码为gzip时,字符串在日志中显示为非utf8 gzip字符。这似乎是golang的疏忽,但可能是我在文档中遗漏了一些东西,我已经读了好几遍了。我不能在这里发布日志,因为这些字符不是utf8字符,所以它们无论如何都不会显示在这个网站上。所以,我知道你的想法,只要抓取gzip内容并使用一种方法删除gzip压缩。如果DumpResponse的响应部分不是gzip,部分是标准的utf8,并且没有办法将各个部分彼此分开,那就太好了

所以我知道你要说什么,为什么不直接接受原始响应,如下面的和gzip解码,并且“不”使用DumpResponse。我也可以这样做,但以下方面存在问题:

var reader io.Reader
startreader := httputility.NewChunkedReader(reader)
switch response.Header.Get("Content-Encoding") {
case "gzip":
    startreader, err = gzip.NewReader(response.Body)
    log.Println("Response body gzip: ")
    buf := new(bytes.Buffer)
    buf.ReadFrom(startreader)
    b := buf.Bytes()
    s := *(*string)(unsafe.Pointer(&b))
    for name, value := range response.Header {
        var hvaluecomp string = ""
        for i := 0; i < len(value); i++ {
            hvaluecomp += value[i]
        }
        response.Header.Add(name,hvaluecomp)
    }
    log.Printf("%s", s)



default:
    startreader = response.Body
    buf := new(bytes.Buffer)
    buf.ReadFrom(startreader)
    b := buf.Bytes()
    s := *(*string)(unsafe.Pointer(&b))
    for name, value := range response.Header {
        fmt.Printf("%v: %v\n", name, value)
    }
    log.Printf("%s", s)
}
var读取器io.reader
startreader:=httputility.NewChunkedReader(读取器)
switch response.Header.Get(“内容编码”){
案例“gzip”:
startreader,err=gzip.NewReader(response.Body)
Println(“响应体gzip:”)
buf:=新(字节.缓冲区)
buf.ReadFrom(startreader)
b:=buf.Bytes()
s:=*(*字符串)(不安全的.指针(&b))
对于名称,值:=范围响应.Header{
var hvaluecomp string=“”
对于i:=0;i
上面的问题是,通过读卡器只能读取一次响应,之后反向代理无法再读取响应,它会使代理响应返回到浏览器nil=),因此我再次遇到失败。我无法想象编码golang的人会错过解码gzip,只是奇怪,它似乎很简单

最后,我的问题是,DumpResponse是否给了我解压gzip的能力,这样我就可以记录实际的响应而不是非utf8字符?在调试生产产品的问题时,这对日志读取器没有好处。这将使内置的golang反向代理在我眼中毫无用处,我将自己开始开发

DumpResponse是否给我解压gzip的能力

不,没有


在我看来,主要的问题似乎既不是反向代理也不是DumpResponse,而是您试图“记录”二进制数据:无论是gzip还是其他二进制数据(如图像)。只需修复日志逻辑:如果原始主体是二进制的,那么应该呈现它的某种表示或转换。对于gziped,首先将其压缩(但这可能仍然是二进制的“非utf8”数据,不适合记录)。关注真正的问题:如何“记录”二进制数据。

答案是复制流,然后可以使用第二个变量将流重新发布回request.body对象,这样就不会丢失任何数据

buf, _ := ioutil.ReadAll(response.Body)
responseuse1 := ioutil.NopCloser(bytes.NewBuffer(buf))
responsehold := ioutil.NopCloser(bytes.NewBuffer(buf))
拉动日志记录的方法:extractLogging(responseuse1) 将挡块推回身体,使其保持原样:response.body=responsehold


返回响应

并请停止执行类似
*(*string)(unsafe.Pointer(&b))
的操作。拜托,你有没有读过这个问题,我从回复中得到的信息是动态的,我无法控制它,我甚至有疑问我是否应该发布到这个网站上,这是我见过的最愚蠢的答案。你能至少试着回答这个问题吗?仅供参考,我不是在记录二进制数据,我是在转换数据,但我想你必须先理解这个定义明确的问题,然后才能给出一个明智的答案。我会在找到答案后发布我自己的答案。仅供参考,我喜欢stack,所以不要误解我,我经常使用它。有时你会遇到沃尔克,有时你会遇到对问题不屑一顾的人。5050次机会,我得到了沃克。