如何在 Golang 中间件中读取请求正文两次?
Posted
技术标签:
【中文标题】如何在 Golang 中间件中读取请求正文两次?【英文标题】:How to read request body twice in Golang middleware? 【发布时间】:2018-04-07 11:11:03 【问题描述】:在中间件中,我想读取请求正文以执行一些检查。然后,请求被传递到下一个中间件,在该中间件将再次读取正文。 这是我的工作:
bodyBytes, _ := ioutil.ReadAll(req.Body)
req.Body = ioutil.NopCloser(bytes.NewBuffer(bodyBytes))
// use bodyBytes
// pass to next middleware
现在,req.Body.Close 什么都不做。由于之前的 req.Body.Close 实现做了一些连接处理,它会中断吗?
【问题讨论】:
Golang read request body 的相关/可能重复。 我读过。在答案中,原始主体没有关闭,这令人困惑。 在服务器端你不需要关闭请求体。Request.Body
:“服务器将关闭请求体。ServeHTTP Handler 不需要。”
不,原来的“关闭”并没有丢失。您只需为导出的Request.Body
字段分配一个新值。这不是唯一需要关闭的对原始正文阅读器的引用。
标题有误导性,应该是读取请求正文
【参考方案1】:
由于之前的 req.Body.Close 实现做了一些连接处理,它会中断吗?
没有。
但是您的代码有问题:阅读完所有内容后,您应该关闭 req.Body。然后你像你一样构造一个新的 ReadCloser 并将它交给下一个中间件(它本身或更底层的东西负责关闭。)
bodyBytes, _ := ioutil.ReadAll(req.Body)
req.Body.Close() // must close
req.Body = ioutil.NopCloser(bytes.NewBuffer(bodyBytes))
【讨论】:
谢谢。也许,我应该重新表述我的问题,因为我想得到一些理解。在 golang 客户端中,我关闭响应主体以将连接返回到池中,以便随后在其他请求中重用(如果我错了,请纠正我)。 req.body.close 在服务器中到底做了什么? 我怀疑是否有一个简单的答案。首先,它可能不会在服务器中执行任何操作。在客户端上,是否重用连接也很困难,这更多地取决于客户端和服务器同意做什么,而不是您关闭主体。但是:当然,您必须关闭原始主体。我会更新我的答案。 在你的代码中,不应该只在 err 为 nil 时才关闭正文吗? 在服务器端你不需要关闭请求体。Request.Body
:“服务器将关闭请求体。ServeHTTP Handler 不需要。”
@Sergey 我不明白。您应该关闭 req.Body,即使从中读取会产生错误。这是无关的。您是否考虑不关闭请求本身会产生错误?以上是关于如何在 Golang 中间件中读取请求正文两次?的主要内容,如果未能解决你的问题,请参考以下文章
如何在 asp net core 2.2 中间件中多次读取请求正文?
如何使用 Golang 的 net/http 包读取流响应正文?
如何使用 WEnviroment 读取 Wt 中的原始请求正文?