]> Cypherpunks repositories - gostls13.git/commitdiff
net/http: make Client propagate Request.Cancel over redirected requests
authorOlivier Poitrey <rs@dailymotion.com>
Thu, 21 Jan 2016 06:53:50 +0000 (22:53 -0800)
committerBrad Fitzpatrick <bradfitz@golang.org>
Thu, 21 Jan 2016 17:00:42 +0000 (17:00 +0000)
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/18810
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>

src/net/http/client.go
src/net/http/client_test.go

index faac5d4e2e74b7fc784e7644d6a86d130801e69d..3106d229da6f7c2c448c397980c540f5cf1315e1 100644 (file)
@@ -445,6 +445,7 @@ func (c *Client) doFollowingRedirects(ireq *Request, shouldRedirect func(int) bo
        for redirect := 0; ; redirect++ {
                if redirect != 0 {
                        nreq := new(Request)
+                       nreq.Cancel = ireq.Cancel
                        nreq.Method = ireq.Method
                        if ireq.Method == "POST" || ireq.Method == "PUT" {
                                nreq.Method = "GET"
index cfad71e0295f1025d04baf846fc673bf1ed17fe6..8939dc8baf9cc9ac4e95784fac3ca897543c5f4b 100644 (file)
@@ -240,7 +240,9 @@ func TestClientRedirects(t *testing.T) {
 
        var checkErr error
        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
                return checkErr
        }}
@@ -260,6 +262,20 @@ func TestClientRedirects(t *testing.T) {
                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")
        res, err = c.Get(ts.URL)
        if urlError, ok := err.(*url.Error); !ok || urlError.Err != checkErr {