From: Edan B <3d4nb3@gmail.com> Date: Sat, 11 Nov 2017 08:10:14 +0000 (+0200) Subject: net/http/httputil: make ReverseProxy close response body if ModifyResponse returns... X-Git-Tag: go1.10beta1~312 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=d96ebf8a6d26f6f5bcf46f9da04def4ad8ec08d9;p=gostls13.git net/http/httputil: make ReverseProxy close response body if ModifyResponse returns an error Fixes #22658 Change-Id: I00e2b007d77b6f54798f7755d0b08e4fea824392 Reviewed-on: https://go-review.googlesource.com/77170 Reviewed-by: Emmanuel Odeke Run-TryBot: Emmanuel Odeke TryBot-Result: Gobot Gobot --- diff --git a/src/net/http/httputil/reverseproxy.go b/src/net/http/httputil/reverseproxy.go index a0f36d1221..b96bb21019 100644 --- a/src/net/http/httputil/reverseproxy.go +++ b/src/net/http/httputil/reverseproxy.go @@ -207,6 +207,7 @@ func (p *ReverseProxy) ServeHTTP(rw http.ResponseWriter, req *http.Request) { if err := p.ModifyResponse(res); err != nil { p.logf("http: proxy error: %v", err) rw.WriteHeader(http.StatusBadGateway) + res.Body.Close() return } } diff --git a/src/net/http/httputil/reverseproxy_test.go b/src/net/http/httputil/reverseproxy_test.go index 37a9992375..2232042d3e 100644 --- a/src/net/http/httputil/reverseproxy_test.go +++ b/src/net/http/httputil/reverseproxy_test.go @@ -769,3 +769,47 @@ type roundTripperFunc func(req *http.Request) (*http.Response, error) func (fn roundTripperFunc) RoundTrip(req *http.Request) (*http.Response, error) { return fn(req) } + +func TestModifyResponseClosesBody(t *testing.T) { + req, _ := http.NewRequest("GET", "http://foo.tld/", nil) + req.RemoteAddr = "1.2.3.4:56789" + closeCheck := new(checkCloser) + logBuf := new(bytes.Buffer) + outErr := errors.New("ModifyResponse error") + rp := &ReverseProxy{ + Director: func(req *http.Request) {}, + Transport: &staticTransport{&http.Response{ + StatusCode: 200, + Body: closeCheck, + }}, + ErrorLog: log.New(logBuf, "", 0), + ModifyResponse: func(*http.Response) error { + return outErr + }, + } + rec := httptest.NewRecorder() + rp.ServeHTTP(rec, req) + res := rec.Result() + if g, e := res.StatusCode, http.StatusBadGateway; g != e { + t.Errorf("got res.StatusCode %d; expected %d", g, e) + } + if !closeCheck.closed { + t.Errorf("body should have been closed") + } + if g, e := logBuf.String(), outErr.Error(); !strings.Contains(g, e) { + t.Errorf("ErrorLog %q does not contain %q", g, e) + } +} + +type checkCloser struct { + closed bool +} + +func (cc *checkCloser) Close() error { + cc.closed = true + return nil +} + +func (cc *checkCloser) Read(b []byte) (int, error) { + return len(b), nil +}