Commit f8f4cfa5 authored by Olivier Poitrey's avatar Olivier Poitrey Committed by Brad Fitzpatrick

net/http: make Client propagate Request.Cancel over redirected requests

On HTTP redirect, the HTTP client creates a new request and don't copy
over the Cancel channel. This prevents any redirected request from being
cancelled.

Fixes #14053

Change-Id: I467cdd4aadcae8351b6e9733fc582b7985b8b9d3
Reviewed-on: https://go-review.googlesource.com/18810Reviewed-by: default avatarBrad Fitzpatrick <bradfitz@golang.org>
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
parent 33a784e1
...@@ -445,6 +445,7 @@ func (c *Client) doFollowingRedirects(ireq *Request, shouldRedirect func(int) bo ...@@ -445,6 +445,7 @@ func (c *Client) doFollowingRedirects(ireq *Request, shouldRedirect func(int) bo
for redirect := 0; ; redirect++ { for redirect := 0; ; redirect++ {
if redirect != 0 { if redirect != 0 {
nreq := new(Request) nreq := new(Request)
nreq.Cancel = ireq.Cancel
nreq.Method = ireq.Method nreq.Method = ireq.Method
if ireq.Method == "POST" || ireq.Method == "PUT" { if ireq.Method == "POST" || ireq.Method == "PUT" {
nreq.Method = "GET" nreq.Method = "GET"
......
...@@ -240,7 +240,9 @@ func TestClientRedirects(t *testing.T) { ...@@ -240,7 +240,9 @@ func TestClientRedirects(t *testing.T) {
var checkErr error var checkErr error
var lastVia []*Request var lastVia []*Request
c = &Client{CheckRedirect: func(_ *Request, via []*Request) error { var lastReq *Request
c = &Client{CheckRedirect: func(req *Request, via []*Request) error {
lastReq = req
lastVia = via lastVia = via
return checkErr return checkErr
}} }}
...@@ -260,6 +262,20 @@ func TestClientRedirects(t *testing.T) { ...@@ -260,6 +262,20 @@ func TestClientRedirects(t *testing.T) {
t.Errorf("expected lastVia to have contained %d elements; got %d", e, g) t.Errorf("expected lastVia to have contained %d elements; got %d", e, g)
} }
// Test that Request.Cancel is propagated between requests (Issue 14053)
creq, _ := NewRequest("HEAD", ts.URL, nil)
cancel := make(chan struct{})
creq.Cancel = cancel
if _, err := c.Do(creq); err != nil {
t.Fatal(err)
}
if lastReq == nil {
t.Fatal("didn't see redirect")
}
if lastReq.Cancel != cancel {
t.Errorf("expected lastReq to have the cancel channel set on the inital req")
}
checkErr = errors.New("no redirects allowed") checkErr = errors.New("no redirects allowed")
res, err = c.Get(ts.URL) res, err = c.Get(ts.URL)
if urlError, ok := err.(*url.Error); !ok || urlError.Err != checkErr { if urlError, ok := err.(*url.Error); !ok || urlError.Err != checkErr {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment