diff --git a/lib/kube/proxy/forwarder.go b/lib/kube/proxy/forwarder.go index 1470e086b77bc..2022f4289e428 100644 --- a/lib/kube/proxy/forwarder.go +++ b/lib/kube/proxy/forwarder.go @@ -19,6 +19,7 @@ package proxy import ( + "bytes" "context" "crypto/tls" "encoding/json" @@ -2138,6 +2139,20 @@ func (f *Forwarder) catchAll(authCtx *authContext, w http.ResponseWriter, req *h return nil, trace.Wrap(err) } + // Buffering req.Body so that HTTP/2 transport can retry + if req.Body != nil && req.Body != http.NoBody { + bodyBytes, err := io.ReadAll(req.Body) + if err != nil { + return nil, trace.Wrap(err) + } + req.Body.Close() + req.Body = io.NopCloser(bytes.NewReader(bodyBytes)) + req.ContentLength = int64(len(bodyBytes)) + req.GetBody = func() (io.ReadCloser, error) { + return io.NopCloser(bytes.NewReader(bodyBytes)), nil + } + } + isLocalKubeCluster := sess.isLocalKubernetesCluster isListRequest := authCtx.requestVerb == types.KubeVerbList // Watch requests can be send to a single resource or to a collection of resources.