fix(vhost): avoid request body access after CONNECT hijack (#5562)

This commit is contained in:
fatedier
2026-10-09 23:53:05 +08:00
committed by GitHub
parent 9c7d9898b3
commit 1cc2dd8a23
2 changed files with 196 additions and 7 deletions
+21 -1
View File
@@ -206,12 +206,28 @@ func checkRouteAuthByRequest(req *http.Request, rc *RouteConfig) bool {
}
func (rp *HTTPReverseProxy) connectHandler(rw http.ResponseWriter, req *http.Request) {
if req.ContentLength > 0 || len(req.TransferEncoding) > 0 {
http.Error(rw, http.StatusText(http.StatusBadRequest), http.StatusBadRequest)
return
}
hj, ok := rw.(http.Hijacker)
if !ok {
rw.WriteHeader(http.StatusInternalServerError)
return
}
// Forward only CONNECT headers; the original Body must not be used after Hijack.
outreq := req.Clone(req.Context())
outreq.Body = nil
outreq.GetBody = nil
outreq.ContentLength = 0
outreq.TransferEncoding = nil
outreq.Trailer = nil
outreq.Header.Del("Content-Length")
outreq.Header.Del("Transfer-Encoding")
outreq.Header.Del("Trailer")
client, buffered, err := hj.Hijack()
if err != nil {
rw.WriteHeader(http.StatusInternalServerError)
@@ -224,7 +240,11 @@ func (rp *HTTPReverseProxy) connectHandler(rw http.ResponseWriter, req *http.Req
client.Close()
return
}
_ = req.Write(remote)
if err := outreq.Write(remote); err != nil {
_ = remote.Close()
_ = client.Close()
return
}
go libio.Join(remote, libio.WrapReadWriteCloser(buffered.Reader, client, client.Close))
}