在不修改请求状态的情况下读取 http.Request 的正文? [英] Reading body of http.Request without modifying request state?

查看:19
本文介绍了在不修改请求状态的情况下读取 http.Request 的正文?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a type implementing the http.Handler interface where, in its ServeHTTP method, incoming HTTP requests are inspected, some action is taken, and then the requests are forwarded to a reverse proxy handler (httputil.NewSingleHostReverseProxy).

这很好用,只要我只检查基本的请求属性,例如 URL 或标头.

This works fine, so long as I'm only inspecting the basic request properties, such as the URL or headers.

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

When I want to inspect the body of an incoming POST request, e.g. by calling req.ParseForm() and then using the req.Form property, I run into an error once the request is passed onto the reverse proxy:

http: 代理错误:http: Request.ContentLength=687 with Body length 0

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

I imagine this happens because looking at the body of the HTTP request causes the req.Body.Reader stream to be drained, meaning it cannot be read again by the proxy handler.

我一直在尝试诸如 io.Copy()bufio.Peek() 之类的东西,但我并没有真正取得任何进展.

I've been playing with things like io.Copy() and bufio.Peek(), but I'm not really getting anywhere.

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

Is there a way to peek at the HTTP request body (and use the built-in parsing of req.ParseForm etc.), while leaving the original request object in its original state, so that it can be passed to the reverse proxy?

推荐答案

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

Try reading into a buffer and then using the buffer to back two new readers, one for you to use, and one for subsequent consumers to use. For example, imagine that we want to modify the following code:

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 的调用中.

Note that *bytes.Buffer does not have a Close() error method, so it doesn't implement the io.ReadCloser interface. Thus, we have to wrap our *bytes.Buffer values in calls to ioutil.NopCloser.

这篇关于在不修改请求状态的情况下读取 http.Request 的正文?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆