mirror of https://github.com/golang/go.git
net/http/httputil: ensure DumpRequestOut dumps all of Body
Bodies larger than 8KB (the default bufio reader size) weren't being dumped. Force a read of the body so they're teed into the response buffer. Thanks to Steven Hartland for identifying the problem. Fixes #8089 LGTM=r R=golang-codereviews, r CC=adg, golang-codereviews https://golang.org/cl/144650044
This commit is contained in:
parent
1b89cd1658
commit
4a532c664d
|
|
@ -95,19 +95,27 @@ func DumpRequestOut(req *http.Request, body bool) ([]byte, error) {
|
||||||
// with a dummy response.
|
// with a dummy response.
|
||||||
var buf bytes.Buffer // records the output
|
var buf bytes.Buffer // records the output
|
||||||
pr, pw := io.Pipe()
|
pr, pw := io.Pipe()
|
||||||
|
defer pr.Close()
|
||||||
|
defer pw.Close()
|
||||||
dr := &delegateReader{c: make(chan io.Reader)}
|
dr := &delegateReader{c: make(chan io.Reader)}
|
||||||
// Wait for the request before replying with a dummy response:
|
// Wait for the request before replying with a dummy response:
|
||||||
go func() {
|
go func() {
|
||||||
http.ReadRequest(bufio.NewReader(pr))
|
req, err := http.ReadRequest(bufio.NewReader(pr))
|
||||||
|
if err == nil {
|
||||||
|
// Ensure all the body is read; otherwise
|
||||||
|
// we'll get a partial dump.
|
||||||
|
io.Copy(ioutil.Discard, req.Body)
|
||||||
|
req.Body.Close()
|
||||||
|
}
|
||||||
dr.c <- strings.NewReader("HTTP/1.1 204 No Content\r\n\r\n")
|
dr.c <- strings.NewReader("HTTP/1.1 204 No Content\r\n\r\n")
|
||||||
}()
|
}()
|
||||||
|
|
||||||
t := &http.Transport{
|
t := &http.Transport{
|
||||||
|
DisableKeepAlives: true,
|
||||||
Dial: func(net, addr string) (net.Conn, error) {
|
Dial: func(net, addr string) (net.Conn, error) {
|
||||||
return &dumpConn{io.MultiWriter(&buf, pw), dr}, nil
|
return &dumpConn{io.MultiWriter(&buf, pw), dr}, nil
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
defer t.CloseIdleConnections()
|
|
||||||
|
|
||||||
_, err := t.RoundTrip(reqSend)
|
_, err := t.RoundTrip(reqSend)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -111,6 +111,30 @@ var dumpTests = []dumpTest{
|
||||||
|
|
||||||
NoBody: true,
|
NoBody: true,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// Request with Body > 8196 (default buffer size)
|
||||||
|
{
|
||||||
|
Req: http.Request{
|
||||||
|
Method: "POST",
|
||||||
|
URL: &url.URL{
|
||||||
|
Scheme: "http",
|
||||||
|
Host: "post.tld",
|
||||||
|
Path: "/",
|
||||||
|
},
|
||||||
|
ContentLength: 8193,
|
||||||
|
ProtoMajor: 1,
|
||||||
|
ProtoMinor: 1,
|
||||||
|
},
|
||||||
|
|
||||||
|
Body: bytes.Repeat([]byte("a"), 8193),
|
||||||
|
|
||||||
|
WantDumpOut: "POST / HTTP/1.1\r\n" +
|
||||||
|
"Host: post.tld\r\n" +
|
||||||
|
"User-Agent: Go 1.1 package http\r\n" +
|
||||||
|
"Content-Length: 8193\r\n" +
|
||||||
|
"Accept-Encoding: gzip\r\n\r\n" +
|
||||||
|
strings.Repeat("a", 8193),
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestDumpRequest(t *testing.T) {
|
func TestDumpRequest(t *testing.T) {
|
||||||
|
|
@ -125,6 +149,8 @@ func TestDumpRequest(t *testing.T) {
|
||||||
tt.Req.Body = ioutil.NopCloser(bytes.NewReader(b))
|
tt.Req.Body = ioutil.NopCloser(bytes.NewReader(b))
|
||||||
case func() io.ReadCloser:
|
case func() io.ReadCloser:
|
||||||
tt.Req.Body = b()
|
tt.Req.Body = b()
|
||||||
|
default:
|
||||||
|
t.Fatalf("Test %d: unsupported Body of %T", i, tt.Body)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
setBody()
|
setBody()
|
||||||
|
|
@ -159,7 +185,9 @@ func TestDumpRequest(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if dg := runtime.NumGoroutine() - numg0; dg > 4 {
|
if dg := runtime.NumGoroutine() - numg0; dg > 4 {
|
||||||
t.Errorf("Unexpectedly large number of new goroutines: %d new", dg)
|
buf := make([]byte, 4096)
|
||||||
|
buf = buf[:runtime.Stack(buf, true)]
|
||||||
|
t.Errorf("Unexpectedly large number of new goroutines: %d new: %s", dg, buf)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue