Skip to content

Commit c0dd201

Browse files
bradfitzbroady
authored andcommitted
[release-branch.go1.5] net/http/httputil: permit nil request body in ReverseProxy
Accepting a request with a nil body was never explicitly supported but happened to work in the past. This doesn't happen in most cases because usually people pass a Server's incoming Request to the ReverseProxy's ServeHTTP method, and incoming server requests are guaranteed to have non-nil bodies. Still, it's a regression, so fix. Fixes #12344 Change-Id: Id9a5a47aea3f2875d195b66c9a5f8581c4ca2aed Reviewed-on: https://go-review.googlesource.com/13935 Reviewed-by: Ian Lance Taylor <[email protected]> Run-TryBot: Brad Fitzpatrick <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-on: https://go-review.googlesource.com/14245
1 parent a7e30ce commit c0dd201

File tree

2 files changed

+43
-1
lines changed

2 files changed

+43
-1
lines changed

src/net/http/httputil/reverseproxy.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ type requestCanceler interface {
105105
}
106106

107107
type runOnFirstRead struct {
108-
io.Reader
108+
io.Reader // optional; nil means empty body
109109

110110
fn func() // Run before first Read, then set to nil
111111
}
@@ -115,6 +115,9 @@ func (c *runOnFirstRead) Read(bs []byte) (int, error) {
115115
c.fn()
116116
c.fn = nil
117117
}
118+
if c.Reader == nil {
119+
return 0, io.EOF
120+
}
118121
return c.Reader.Read(bs)
119122
}
120123

src/net/http/httputil/reverseproxy_test.go

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
package httputil
88

99
import (
10+
"bufio"
1011
"io/ioutil"
1112
"log"
1213
"net/http"
@@ -281,3 +282,41 @@ func TestReverseProxyCancellation(t *testing.T) {
281282
t.Fatal("DefaultClient.Do() returned nil error")
282283
}
283284
}
285+
286+
func req(t *testing.T, v string) *http.Request {
287+
req, err := http.ReadRequest(bufio.NewReader(strings.NewReader(v)))
288+
if err != nil {
289+
t.Fatal(err)
290+
}
291+
return req
292+
}
293+
294+
// Issue 12344
295+
func TestNilBody(t *testing.T) {
296+
backend := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
297+
w.Write([]byte("hi"))
298+
}))
299+
defer backend.Close()
300+
301+
frontend := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
302+
backURL, _ := url.Parse(backend.URL)
303+
rp := NewSingleHostReverseProxy(backURL)
304+
r := req(t, "GET / HTTP/1.0\r\n\r\n")
305+
r.Body = nil // this accidentally worked in Go 1.4 and below, so keep it working
306+
rp.ServeHTTP(w, r)
307+
}))
308+
defer frontend.Close()
309+
310+
res, err := http.Get(frontend.URL)
311+
if err != nil {
312+
t.Fatal(err)
313+
}
314+
defer res.Body.Close()
315+
slurp, err := ioutil.ReadAll(res.Body)
316+
if err != nil {
317+
t.Fatal(err)
318+
}
319+
if string(slurp) != "hi" {
320+
t.Errorf("Got %q; want %q", slurp, "hi")
321+
}
322+
}

0 commit comments

Comments
 (0)