Skip to content

Commit 236db3c

Browse files
Merge pull request #113988 from liggitt/automated-cherry-pick-of-#113933-upstream-release-1.26
[1.26.1] Automated cherry pick of #113933: Limit request retrying to []byte request bodies Kubernetes-commit: 7c0eb3be77cb388bc98a9ddc33371e0b6d3c27da
2 parents 95a14c3 + ebb499f commit 236db3c

File tree

4 files changed

+75
-206
lines changed

4 files changed

+75
-206
lines changed

rest/request.go

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ import (
3434
"time"
3535

3636
"golang.org/x/net/http2"
37+
3738
"k8s.io/apimachinery/pkg/api/errors"
3839
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
3940
"k8s.io/apimachinery/pkg/runtime"
@@ -116,8 +117,11 @@ type Request struct {
116117
subresource string
117118

118119
// output
119-
err error
120-
body io.Reader
120+
err error
121+
122+
// only one of body / bodyBytes may be set. requests using body are not retriable.
123+
body io.Reader
124+
bodyBytes []byte
121125

122126
retryFn requestRetryFunc
123127
}
@@ -443,12 +447,15 @@ func (r *Request) Body(obj interface{}) *Request {
443447
return r
444448
}
445449
glogBody("Request Body", data)
446-
r.body = bytes.NewReader(data)
450+
r.body = nil
451+
r.bodyBytes = data
447452
case []byte:
448453
glogBody("Request Body", t)
449-
r.body = bytes.NewReader(t)
454+
r.body = nil
455+
r.bodyBytes = t
450456
case io.Reader:
451457
r.body = t
458+
r.bodyBytes = nil
452459
case runtime.Object:
453460
// callers may pass typed interface pointers, therefore we must check nil with reflection
454461
if reflect.ValueOf(t).IsNil() {
@@ -465,7 +472,8 @@ func (r *Request) Body(obj interface{}) *Request {
465472
return r
466473
}
467474
glogBody("Request Body", data)
468-
r.body = bytes.NewReader(data)
475+
r.body = nil
476+
r.bodyBytes = data
469477
r.SetHeader("Content-Type", r.c.content.ContentType)
470478
default:
471479
r.err = fmt.Errorf("unknown type used for body: %+v", obj)
@@ -825,9 +833,6 @@ func (r *Request) Stream(ctx context.Context) (io.ReadCloser, error) {
825833
if err != nil {
826834
return nil, err
827835
}
828-
if r.body != nil {
829-
req.Body = io.NopCloser(r.body)
830-
}
831836
resp, err := client.Do(req)
832837
updateURLMetrics(ctx, r, resp, err)
833838
retry.After(ctx, r, resp, err)
@@ -889,8 +894,20 @@ func (r *Request) requestPreflightCheck() error {
889894
}
890895

891896
func (r *Request) newHTTPRequest(ctx context.Context) (*http.Request, error) {
897+
var body io.Reader
898+
switch {
899+
case r.body != nil && r.bodyBytes != nil:
900+
return nil, fmt.Errorf("cannot set both body and bodyBytes")
901+
case r.body != nil:
902+
body = r.body
903+
case r.bodyBytes != nil:
904+
// Create a new reader specifically for this request.
905+
// Giving each request a dedicated reader allows retries to avoid races resetting the request body.
906+
body = bytes.NewReader(r.bodyBytes)
907+
}
908+
892909
url := r.URL().String()
893-
req, err := http.NewRequest(r.verb, url, r.body)
910+
req, err := http.NewRequest(r.verb, url, body)
894911
if err != nil {
895912
return nil, err
896913
}

0 commit comments

Comments
 (0)