mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
net/http: don't panic after request if Handler sets Request.Body to nil
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>
This commit is contained in:
parent
9179c9cb5c
commit
b1050542c1
2 changed files with 30 additions and 3 deletions
|
|
@ -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) {
|
func BenchmarkClientServer(b *testing.B) {
|
||||||
b.ReportAllocs()
|
b.ReportAllocs()
|
||||||
b.StopTimer()
|
b.StopTimer()
|
||||||
|
|
|
||||||
|
|
@ -317,8 +317,9 @@ func (cw *chunkWriter) close() {
|
||||||
type response struct {
|
type response struct {
|
||||||
conn *conn
|
conn *conn
|
||||||
req *Request // request for this response
|
req *Request // request for this response
|
||||||
wroteHeader bool // reply header has been (logically) written
|
reqBody io.ReadCloser
|
||||||
wroteContinue bool // 100 Continue response was written
|
wroteHeader bool // reply header has been (logically) written
|
||||||
|
wroteContinue bool // 100 Continue response was written
|
||||||
|
|
||||||
w *bufio.Writer // buffers output in chunks to chunkWriter
|
w *bufio.Writer // buffers output in chunks to chunkWriter
|
||||||
cw chunkWriter
|
cw chunkWriter
|
||||||
|
|
@ -658,6 +659,7 @@ func (c *conn) readRequest() (w *response, err error) {
|
||||||
w = &response{
|
w = &response{
|
||||||
conn: c,
|
conn: c,
|
||||||
req: req,
|
req: req,
|
||||||
|
reqBody: req.Body,
|
||||||
handlerHeader: make(Header),
|
handlerHeader: make(Header),
|
||||||
contentLength: -1,
|
contentLength: -1,
|
||||||
}
|
}
|
||||||
|
|
@ -1167,7 +1169,7 @@ func (w *response) finishRequest() {
|
||||||
|
|
||||||
// Close the body (regardless of w.closeAfterReply) so we can
|
// Close the body (regardless of w.closeAfterReply) so we can
|
||||||
// re-use its bufio.Reader later safely.
|
// re-use its bufio.Reader later safely.
|
||||||
w.req.Body.Close()
|
w.reqBody.Close()
|
||||||
|
|
||||||
if w.req.MultipartForm != nil {
|
if w.req.MultipartForm != nil {
|
||||||
w.req.MultipartForm.RemoveAll()
|
w.req.MultipartForm.RemoveAll()
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue