]> Cypherpunks repositories - gostls13.git/commitdiff
net/http: don't panic after request if Handler sets Request.Body to nil
authorBrad Fitzpatrick <bradfitz@golang.org>
Tue, 3 Nov 2015 20:04:20 +0000 (12:04 -0800)
committerBrad Fitzpatrick <bradfitz@golang.org>
Wed, 4 Nov 2015 00:00:15 +0000 (00:00 +0000)
The Server's server goroutine was panicing (but recovering) when
cleaning up after handling a request. It was pretty harmless (it just
closed that one connection and didn't kill the whole process) but it
was distracting.

Updates #13135

Change-Id: I2a0ce9e8b52c8d364e3f4ce245e05c6f8d62df14
Reviewed-on: https://go-review.googlesource.com/16572
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Andrew Gerrand <adg@golang.org>
src/net/http/serve_test.go
src/net/http/server.go

index 3bd3db4a69b1033d3b858528b29ad3f6466aacfc..f3454848b7577c26c85ce1c5f07d1a7ff3f503a4 100644 (file)
@@ -3381,6 +3381,31 @@ func TestHandlerFinishSkipBigContentLengthRead(t *testing.T) {
        }
 }
 
+func TestHandlerSetsBodyNil(t *testing.T) {
+       defer afterTest(t)
+       ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+               r.Body = nil
+               fmt.Fprintf(w, "%v", r.RemoteAddr)
+       }))
+       defer ts.Close()
+       get := func() string {
+               res, err := Get(ts.URL)
+               if err != nil {
+                       t.Fatal(err)
+               }
+               defer res.Body.Close()
+               slurp, err := ioutil.ReadAll(res.Body)
+               if err != nil {
+                       t.Fatal(err)
+               }
+               return string(slurp)
+       }
+       a, b := get(), get()
+       if a != b {
+               t.Errorf("Failed to reuse connections between requests: %v vs %v", a, b)
+       }
+}
+
 func BenchmarkClientServer(b *testing.B) {
        b.ReportAllocs()
        b.StopTimer()
index e8470efd6bde856fb51b285ba91315b82e0c15f4..979b2eb1e54fac0aacd8de808e50f41db5cd3047 100644 (file)
@@ -317,8 +317,9 @@ func (cw *chunkWriter) close() {
 type response struct {
        conn          *conn
        req           *Request // request for this response
-       wroteHeader   bool     // reply header has been (logically) written
-       wroteContinue bool     // 100 Continue response was written
+       reqBody       io.ReadCloser
+       wroteHeader   bool // reply header has been (logically) written
+       wroteContinue bool // 100 Continue response was written
 
        w  *bufio.Writer // buffers output in chunks to chunkWriter
        cw chunkWriter
@@ -658,6 +659,7 @@ func (c *conn) readRequest() (w *response, err error) {
        w = &response{
                conn:          c,
                req:           req,
+               reqBody:       req.Body,
                handlerHeader: make(Header),
                contentLength: -1,
        }
@@ -1167,7 +1169,7 @@ func (w *response) finishRequest() {
 
        // Close the body (regardless of w.closeAfterReply) so we can
        // re-use its bufio.Reader later safely.
-       w.req.Body.Close()
+       w.reqBody.Close()
 
        if w.req.MultipartForm != nil {
                w.req.MultipartForm.RemoveAll()