mirror of https://github.com/golang/go.git
net/http: upon http redirect, copy Request.GetBody in new request
This enable http.RoundTripper implementation to retry POST request (let's say after a 500) after a 307/308 redirect. Fixes #73439 Change-Id: I4365ff58b012c7f0d60e0317a08c98b1d48f657e Reviewed-on: https://go-review.googlesource.com/c/go/+/666735 Reviewed-by: Sean Liao <sean@liao.dev> Auto-Submit: Damien Neil <dneil@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Dmitri Shuralyov <dmitshur@google.com> Reviewed-by: Damien Neil <dneil@google.com>
This commit is contained in:
parent
df9888ea4e
commit
b69f50faef
|
|
@ -672,6 +672,7 @@ func (c *Client) do(req *Request) (retres *Response, reterr error) {
|
|||
resp.closeBody()
|
||||
return nil, uerr(err)
|
||||
}
|
||||
req.GetBody = ireq.GetBody
|
||||
req.ContentLength = ireq.ContentLength
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1962,6 +1962,61 @@ func testTransportBodyReadError(t *testing.T, mode testMode) {
|
|||
}
|
||||
}
|
||||
|
||||
// Make sure the retries copies the GetBody in the request.
|
||||
func TestRedirectGetBody(t *testing.T) { run(t, testRedirectGetBody) }
|
||||
|
||||
func testRedirectGetBody(t *testing.T, mode testMode) {
|
||||
ts := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
|
||||
b, err := io.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if err = r.Body.Close(); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if s := string(b); s != "hello" {
|
||||
t.Errorf("expected hello, got %s", s)
|
||||
}
|
||||
if r.URL.Path == "/first" {
|
||||
Redirect(w, r, "/second", StatusTemporaryRedirect)
|
||||
return
|
||||
}
|
||||
w.Write([]byte("world"))
|
||||
})).ts
|
||||
c := ts.Client()
|
||||
c.Transport = &roundTripperGetBody{c.Transport, t}
|
||||
req, err := NewRequest("POST", ts.URL+"/first", strings.NewReader("hello"))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
res, err := c.Do(req.WithT(t))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
b, err := io.ReadAll(res.Body)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err = res.Body.Close(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if s := string(b); s != "world" {
|
||||
t.Fatalf("expected world, got %s", s)
|
||||
}
|
||||
}
|
||||
|
||||
type roundTripperGetBody struct {
|
||||
Transport RoundTripper
|
||||
t *testing.T
|
||||
}
|
||||
|
||||
func (r *roundTripperGetBody) RoundTrip(req *Request) (*Response, error) {
|
||||
if req.GetBody == nil {
|
||||
r.t.Error("missing Request.GetBody")
|
||||
}
|
||||
return r.Transport.RoundTrip(req)
|
||||
}
|
||||
|
||||
type roundTripperWithoutCloseIdle struct{}
|
||||
|
||||
func (roundTripperWithoutCloseIdle) RoundTrip(*Request) (*Response, error) { panic("unused") }
|
||||
|
|
|
|||
Loading…
Reference in New Issue