http.Request.Clone()不是深度克隆?
我想得到一个请求,并使用ParseForm检查一些数据,然后将相同的数据发送给proxy,如果我这样做,我们就有问题了 像这样的错误日志 2020/05/26 15:34:47 http:proxy错误:net/http:http/1.x传输连接已断开:http:ContentLength=32,正文长度为0 所以我最终找到了答案,ParseForm()很好地关闭了Request.body 这是工作代理代码http.Request.Clone()不是深度克隆?,http,go,Http,Go,我想得到一个请求,并使用ParseForm检查一些数据,然后将相同的数据发送给proxy,如果我这样做,我们就有问题了 像这样的错误日志 2020/05/26 15:34:47 http:proxy错误:net/http:http/1.x传输连接已断开:http:ContentLength=32,正文长度为0 所以我最终找到了答案,ParseForm()很好地关闭了Request.body 这是工作代理代码 url, _ := url.Parse(config.GetGameHost()
url, _ := url.Parse(config.GetGameHost())
proxy := httputil.NewSingleHostReverseProxy(url)
r.URL.Host = url.Host
r.URL.Scheme = url.Scheme
r.Header.Set("X-Forwarded-Host", r.Header.Get("Host"))
r.Host = url.Host
proxy.ServeHTTP(w, r)
所以,我想我也需要克隆深层克隆请求,获取我的数据并发送原始请求
今年我也编辑了我的代码
nr := r.Clone(r.Context())
nr.ParseForm()
url, _ := url.Parse(config.GetGameHost())
proxy := httputil.NewSingleHostReverseProxy(url)
r.URL.Host = url.Host
r.URL.Scheme = url.Scheme
r.Header.Set("X-Forwarded-Host", r.Header.Get("Host"))
r.Host = url.Host
proxy.ServeHTTP(w, r)
错误日志将再次显示
2020/05/26 15:49:29 http:proxy错误:net/http:http/1.x传输连接已断开:http:ContentLength=32,正文长度为0
是克隆()不是深度克隆还是我做错了
------------这项工作------------
http.Request.Body只能读取一次,需要复制新的Body
body,err:=ioutil.ReadAll(r)
如果出错!=零{
// ...
}
r2:=r.Clone(r.Context())
//克隆体
r、 Body=ioutil.nocloser(bytes.NewReader(Body))
r2.Body=ioutil.nocloser(bytes.NewReader(Body))
//解析r1,代理r2
r、 ParseForm()
proxy.ServerHTTP(w,r2)
body对象默认为net.Conn多层封装。每次它使用io.Reader接口读取4kb,节省内存使用,通常在从网络读取时使用
因此,正文只能从网络上读取一次。如果希望重复读取实体对象,则应将其全部读取、保存并使用。它会生成深度副本,但副本不会读取实体两次。它只是将io.Reader复制到新请求中,并且无论哪个请求先被读取,都会得到正文,除非您努力复制正文。
body, err := ioutil.ReadAll(r.Body)
if err != nil {
// ...
}
url, _ := url.Parse(config.GetGameHost())
r2 := r.Clone(r.Context())
r.Body = ioutil.NopCloser(bytes.NewReader(body))
r2.Body = ioutil.NopCloser(bytes.NewReader(body))
r.ParseForm()
proxy := httputil.NewSingleHostReverseProxy(url)
proxy.ServeHTTP(w, r2)