Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/http/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
http.Request.Clone()不是深度克隆?_Http_Go - Fatal编程技术网

http.Request.Clone()不是深度克隆?

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()

我想得到一个请求,并使用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())

    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)