duanhong1985 2017-09-18 10:19
浏览 162

记录响应正文时出现Golang DumpResponse gzip问题(反向代理)

I have created a simple reverse proxy in my main.go as follows:

reverseproxy := httputil.NewSingleHostReverseProxy("https://someurl/someuri")

this is working fine, however, I would like to log the response that comes back from the server. I can also do this utilizing the following code inside the standard RoundTrip method recommended by golang:

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

if err != nil {
    return nil, err
}
log.Printf("%s", dumpresp)

All the above works as expected aside from one thing, the response, when Content-Encoding: gzip, the string appears to the logs as non-utf8 gzip characters. it seems to be a golang oversight but maybe there is something i have missed in the documentation, which I have read to its completion a few times. I can't post the logs here because the characters are non utf8 so they would not display on this site anyway. So, I know what your thinking, just grab the gzip content and use a method to remove the gzip compression. That would be great if the response from DumpResponse was not partly gzip and partly standard utf8 with no way to separate the sections from each other.

So I know what your going to say, why not just take the raw response like the following and gzip decode, and "not" use DumpResponse. Well I can do that as well, but there is an issue with the following:

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
", name, value)
    }
    log.Printf("%s", s)
}

The issue with the above is, responses can only be read one time via the reader, after that the response cannot be read by the reverse proxy anymore and it makes the proxy response back to the browser nil =), so again I was met with failure. I cant imagine that the folks coding golang would have missed decoding gzip, just strange, it seems to be so simple.

So in the end, my question is, does DumpResponse give me the ability to decompress gzip so I can log the actual response instead of non utf8 characters? This does the log reader no good when debugging an issue for the production product. This would render the built in golang reverse proxy useless in my eyes and I would start development on my own.

  • 写回答

2条回答 默认 最新

  • dousi3362 2017-09-18 11:10
    关注

    does DumpResponse give me the ability to decompress gzip

    No it does not.

    To me it seems as if the major problem is neither the reverse proxy nor DumpResponse but that you are trying to "log" binary data: Be it gzip, or other binary data like images. Just fix your logging logic: If the raw body is binary you should render some kind of representation or transformation of it. For gziped stuff gunzip it first (but this might still be binary "non utf8" data unsuitable for logging). Focus on the real problem: How to "log" binary data.

    评论

报告相同问题?

悬赏问题

  • ¥15 求帮我调试一下freefem代码
  • ¥15 R语言Rstudio突然无法启动
  • ¥15 关于#matlab#的问题:提取2个图像的变量作为另外一个图像像元的移动量,计算新的位置创建新的图像并提取第二个图像的变量到新的图像
  • ¥15 改算法,照着压缩包里边,参考其他代码封装的格式 写到main函数里
  • ¥15 用windows做服务的同志有吗
  • ¥60 求一个简单的网页(标签-安全|关键词-上传)
  • ¥35 lstm时间序列共享单车预测,loss值优化,参数优化算法
  • ¥15 Python中的request,如何使用ssr节点,通过代理requests网页。本人在泰国,需要用大陆ip才能玩网页游戏,合法合规。
  • ¥100 为什么这个恒流源电路不能恒流?
  • ¥15 有偿求跨组件数据流路径图