当前位置: 首页 > 知识库问答 >
问题:

记录响应体时的Golang Dump响应gzip问题

茹高义
2023-03-14

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

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

这工作正常,但是,我想记录从服务器返回的响应。我也可以使用Go语言推荐的标准RoundTrip方法中的以下代码来实现这一点:

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解码,而“不”使用邓普响应。我也可以这样做,但是下面有一个问题:

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反向代理在我眼中毫无用处,我将自己开始开发

共有2个答案

阎知
2023-03-14

Dump响应是否给我解压gzip的能力

不,没有。

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

笪俊迈
2023-03-14

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

buf, _ := ioutil.ReadAll(response.Body)
responseuse1 := ioutil.NopCloser(bytes.NewBuffer(buf))
responsehold := ioutil.NopCloser(bytes.NewBuffer(buf))

拉动记录的方法:extractLogging(responseuse1)将压具推回身体,使其不受触动:响应。Body=responsehold

返回响应

 类似资料:
  • 我有办法: 此方法返回有关应用程序版本的信息。就像这样: 它是文本,不是xml,不是json,也不是html。 当我尝试使用此方法在REST保证: 我没有收到回复机构: 来自进程的日志: 为什么我没有收到响应体?当我试图在浏览器上转到这个链接时,我收到了一个值。 这是邮递员的一个例子

  • 问题内容: 我正在发出HTTP请求并侦听“数据”: 问题在于响应是分块的,因此“数据”只是发送回的一部分内容。 我如何将全身退回? 问题答案:

  • 我正在尝试访问为执行验证而编写的HttpServerResponse主体。但是,<代码>ctx。回答endHandler(e-

  • 我有一个spring应用程序,它可以与Mobile交换JSON。Spring控制器如下所示: 我想知道,记录http请求正文和响应正文的最佳方式是什么?目前,我有一个定制的json消息转换器,它在从json中创建bean之前记录一个请求正文。我使用CustomTraceInterceptor记录响应正文。不幸的是,CustomTraceInterceptor不允许记录请求正文。 任何更好的解决方案

  • 我是Spring WebClient的新手。有人能建议记录来自另一个WebService的REST请求和响应的最佳方法吗? 我已经看到了一个在问题中记录请求的示例,但也必须记录响应和POST调用的请求。如何记录Spring 5 WebClient调用 谢谢你。

  • 问题内容: 我有一个用rails编写的api,它在每个请求上均以JSON响应进行响应。 响应可能很大,因此我需要使用gzip压缩JSON响应。 想知道如何在Rails控制器中执行此操作? 我加了线 在config.ru中 我还应该在呈现JSON的行中更改某些内容吗? 另外,我如何检查响应是否为gzip格式。 我从终端发出了curl请求,我只看到普通的普通JSON。 问题答案: 对于以gzip格式的