"errors"
"fmt"
"io"
+ "io/ioutil"
"log"
"net/url"
"strings"
}
if shouldRedirect(resp.StatusCode) {
+ // Read the body if small so underlying TCP connection will be re-used.
+ // No need to check for errors: if it fails, Transport won't reuse it anyway.
+ const maxBodySlurpSize = 2 << 10
+ if resp.ContentLength == -1 || resp.ContentLength <= maxBodySlurpSize {
+ io.CopyN(ioutil.Discard, resp.Body, maxBodySlurpSize)
+ }
resp.Body.Close()
if urlStr = resp.Header.Get("Location"); urlStr == "" {
err = errors.New(fmt.Sprintf("%d response missing Location header", resp.StatusCode))
t.Errorf("timeout after %v waiting for timeout of %v", failTime, timeout)
}
}
+
+func TestClientRedirectEatsBody(t *testing.T) {
+ defer afterTest(t)
+ saw := make(chan string, 2)
+ ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+ saw <- r.RemoteAddr
+ if r.URL.Path == "/" {
+ Redirect(w, r, "/foo", StatusFound) // which includes a body
+ }
+ }))
+ defer ts.Close()
+
+ res, err := Get(ts.URL)
+ if err != nil {
+ t.Fatal(err)
+ }
+ _, err = ioutil.ReadAll(res.Body)
+ if err != nil {
+ t.Fatal(err)
+ }
+ res.Body.Close()
+
+ var first string
+ select {
+ case first = <-saw:
+ default:
+ t.Fatal("server didn't see a request")
+ }
+
+ var second string
+ select {
+ case second = <-saw:
+ default:
+ t.Fatal("server didn't see a second request")
+ }
+
+ if first != second {
+ t.Fatal("server saw different client ports before & after the redirect")
+ }
+}