}
var (
- deadline = c.deadline()
- reqs []*Request
- resp *Response
- copyHeaders = c.makeHeadersCopier(req)
+ deadline = c.deadline()
+ reqs []*Request
+ resp *Response
+ copyHeaders = c.makeHeadersCopier(req)
+ reqBodyClosed = false // have we closed the current req.Body?
// Redirect behavior:
redirectMethod string
includeBody bool
)
uerr := func(err error) error {
- req.closeBody()
+ // the body may have been closed already by c.send()
+ if !reqBodyClosed {
+ req.closeBody()
+ }
method := valueOrDefault(reqs[0].Method, "GET")
var urlStr string
if resp != nil && resp.Request != nil {
var err error
var didTimeout func() bool
if resp, didTimeout, err = c.send(req, deadline); err != nil {
+ // c.send() always closes req.Body
+ reqBodyClosed = true
if !deadline.IsZero() && didTimeout() {
err = &httpError{
err: err.Error() + " (Client.Timeout exceeded while awaiting headers)",
t.Errorf("Trailer = %#v; want %#v", res.Trailer, want)
}
}
+
+func TestBadResponseAfterReadingBody(t *testing.T) {
+ defer afterTest(t)
+ cst := newClientServerTest(t, false, HandlerFunc(func(w ResponseWriter, r *Request) {
+ _, err := io.Copy(ioutil.Discard, r.Body)
+ if err != nil {
+ t.Fatal(err)
+ }
+ c, _, err := w.(Hijacker).Hijack()
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer c.Close()
+ fmt.Fprintln(c, "some bogus crap")
+ }))
+ defer cst.close()
+
+ closes := 0
+ res, err := cst.c.Post(cst.ts.URL, "text/plain", countCloseReader{&closes, strings.NewReader("hello")})
+ if err == nil {
+ res.Body.Close()
+ t.Fatal("expected an error to be returned from Post")
+ }
+ if closes != 1 {
+ t.Errorf("closes = %d; want 1", closes)
+ }
+}