我在main.go中创建了一个简单的反向代理,如下所示:
reverseproxy := httputil.NewSingleHostReverseProxy("https://someurl/someuri")
这工作正常,但是,我想记录从服务器返回的响应。我也可以使用golang推荐的标准RoundTrip方法中的以下代码来实现这一点:
response, err := http.DefaultTransport.RoundTrip(request)
dumpresp, err := httputil.DumpResponse(response, true)
if err != nil {
return nil, err
}
log.Printf("%s", dumpresp)
以上所有工作都是预期的,除了一件事,响应,当Content-Encoding: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)
}
上面的问题是,响应只能通过读取器读取一次,之后反向代理不能再读取响应,它会使代理响应返回浏览器nil =),所以我再次遇到了失败。我无法想象编码golang的人会错过解码gzip,只是很奇怪,它似乎很简单。
所以最后,我的问题是,DumpResponse是否能够解压缩gzip,以便我可以记录实际响应而不是非utf8字符?在调试生产产品的问题时,这对日志阅读器没有好处。这会使内置的golang反向代理在我眼中无用,我会自己开始开发。
答案 0 :(得分:0)
DumpResponse让我能够解压缩gzip
不,不。
对我而言,似乎主要问题既不是反向代理也不是DumpResponse,而是你正在尝试&#34; log&#34;二进制数据:无论是gzip还是其他二进制数据,如图像。只需修复您的日志记录逻辑:如果原始主体是二进制文件,您应该呈现某种表示形式或转换它。对于gziped的东西首先是gunzip(但这可能仍然是二进制&#34;非utf8&#34;数据不适合记录)。关注真正的问题:如何&#34; log&#34;二进制数据。
答案 1 :(得分:0)
答案是复制流,然后您可以使用第二个变量将流重新发布回request.body对象,这样您就不会丢失任何数据。
buf, _ := ioutil.ReadAll(response.Body)
responseuse1 := ioutil.NopCloser(bytes.NewBuffer(buf))
responsehold := ioutil.NopCloser(bytes.NewBuffer(buf))
提取日志记录的方法:extractLogging(responseuse1) 将把握推回到身体,使其不受影响:response.Body = responsehold
返回回复