登录
首页 >  Golang >  Go问答

在不修改请求状态的情况下读取 http.Request 的正文?

来源:Golang技术栈

时间:2023-04-29 10:17:53 135浏览 收藏

哈喽!今天心血来潮给大家带来了《在不修改请求状态的情况下读取 http.Request 的正文?》,想必大家应该对Golang都不陌生吧,那么阅读本文就都不会很困难,以下内容主要涉及到golang,若是你正在学习Golang,千万别错过这篇文章~希望能帮助到你!

问题内容

我有一个实现http.Handler接口的类型,在它的ServeHTTP方法中,检查传入的 HTTP 请求,采取一些行动,然后将请求转发到反向代理处理程序 ( httputil.NewSingleHostReverseProxy)。

只要我只检查基本的请求属性,例如 URL 或标头,这就可以正常工作。

当我想检查传入 POST 请求的主体时,例如通过调用req.ParseForm()然后使用该req.Form属性,一旦将请求传递到反向代理,我就会遇到错误:

http: proxy error: http: Request.ContentLength=687 with Body length 0

我想这是因为查看 HTTP 请求的主体会导致req.Body.Reader流被耗尽,这意味着代理处理程序无法再次读取它。

我一直在玩 and 之类的东西io.Copy()bufio.Peek()但我并没有真正得到任何地方。

有没有办法偷看HTTP请求体(并使用内置的解析req.ParseForm等),同时将原始请求对象保持在其原始状态,以便将其传递给反向代理?

正确答案

尝试读入一个缓冲区,然后使用缓冲区支持两个新的读取器,一个供您使用,一个供后续消费者使用。例如,假设我们要修改以下代码:

doStuff(r.Body) // r is an http.Request

我们可以这样做:

buf, _ := ioutil.ReadAll(r.Body)
rdr1 := ioutil.NopCloser(bytes.NewBuffer(buf))
rdr2 := ioutil.NopCloser(bytes.NewBuffer(buf))

doStuff(rdr1)
r.Body = rdr2 // OK since rdr2 implements the io.ReadCloser interface

// Now the program can continue oblivious to the fact that
// r.Body was ever touched.

请注意,*bytes.Buffer它没有Close() error方法,因此它没有实现io.ReadCloser接口。因此,我们必须将我们的*bytes.Buffer值包装在对ioutil.NopCloser.

到这里,我们也就讲完了《在不修改请求状态的情况下读取 http.Request 的正文?》的内容了。个人认为,基础知识的学习和巩固,是为了更好的将其运用到项目中,欢迎关注golang学习网公众号,带你了解更多关于golang的知识点!

声明:本文转载于:Golang技术栈 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>