gpt4 book ai didi

go - 如何记录请求正文(通过中间件)而不进行缓冲?

转载 作者:行者123 更新时间:2023-12-01 22:16:28 25 4
gpt4 key购买 nike

假设我有一个简单的服务器(为简洁起见,省略了错误处理):

func main() {
http.HandleFunc("/", HelloServer)
http.ListenAndServe(":8080", nil)
}

func HelloServer(w http.ResponseWriter, r *http.Request) {
b, _ := ioutil.ReadAll(r.Body)
fmt.Fprintf(w, "The request is: %s", string(b))
}

我需要添加一个简单的中间件,该中间件读取请求的主体并将其记录下来。我已经有了这个可行的解决方案:
func requestLogger(next http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
pr, pw := io.Pipe()
tee := io.TeeReader(r.Body, pw)
r.Body = pr
go func() {
body, _ := ioutil.ReadAll(tee)
defer pw.Close()
log.Printf("This is the logged request: %s", string(body))
}()
next(w, r)
}
}

我通过反复试验直观地找到了该解决方案,所以我不确定在所有情况下该方法是否都有效。这些是关于我自己的解决方案的问题:
  • 为什么我必须手动关闭Pipe在r.Body上遇到EOF时,ioutil.ReadAll()不会将其关闭。
  • 为什么没有阻止? 有一个循环引用,因为TeeReader从它通过管道(r.Body = pr)写入的同一源(r.Body)读取。根据文档,“写入PipeWriter”块直到满足一个或多个读取为止;对于TeeReader,必须在读取完成之前完成写入。
  • 最佳答案

    ioutil.ReadAll()在遇到EOF时不会关闭它吗?



    Package ioutil

    func ReadAll

    func ReadAll(r io.Reader) ([]byte, error)

    ReadAll从r读取直到出现错误或EOF并返回数据
    读。


    那不是记录的行为。另外, io.Reader也不是 io.ReadCloser

    关于go - 如何记录请求正文(通过中间件)而不进行缓冲?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59705848/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com