mirror of
https://github.com/golang/go.git
synced 2025-05-22 16:09:37 +00:00
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 <iant@golang.org> Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org>
This commit is contained in:
parent
b1b3243a1b
commit
a34b8cb733
@ -105,7 +105,7 @@ type requestCanceler interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type runOnFirstRead struct {
|
type runOnFirstRead struct {
|
||||||
io.Reader
|
io.Reader // optional; nil means empty body
|
||||||
|
|
||||||
fn func() // Run before first Read, then set to nil
|
fn func() // Run before first Read, then set to nil
|
||||||
}
|
}
|
||||||
@ -115,6 +115,9 @@ func (c *runOnFirstRead) Read(bs []byte) (int, error) {
|
|||||||
c.fn()
|
c.fn()
|
||||||
c.fn = nil
|
c.fn = nil
|
||||||
}
|
}
|
||||||
|
if c.Reader == nil {
|
||||||
|
return 0, io.EOF
|
||||||
|
}
|
||||||
return c.Reader.Read(bs)
|
return c.Reader.Read(bs)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
package httputil
|
package httputil
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bufio"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
@ -281,3 +282,41 @@ func TestReverseProxyCancellation(t *testing.T) {
|
|||||||
t.Fatal("DefaultClient.Do() returned nil error")
|
t.Fatal("DefaultClient.Do() returned nil error")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func req(t *testing.T, v string) *http.Request {
|
||||||
|
req, err := http.ReadRequest(bufio.NewReader(strings.NewReader(v)))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
return req
|
||||||
|
}
|
||||||
|
|
||||||
|
// Issue 12344
|
||||||
|
func TestNilBody(t *testing.T) {
|
||||||
|
backend := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
w.Write([]byte("hi"))
|
||||||
|
}))
|
||||||
|
defer backend.Close()
|
||||||
|
|
||||||
|
frontend := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
|
||||||
|
backURL, _ := url.Parse(backend.URL)
|
||||||
|
rp := NewSingleHostReverseProxy(backURL)
|
||||||
|
r := req(t, "GET / HTTP/1.0\r\n\r\n")
|
||||||
|
r.Body = nil // this accidentally worked in Go 1.4 and below, so keep it working
|
||||||
|
rp.ServeHTTP(w, r)
|
||||||
|
}))
|
||||||
|
defer frontend.Close()
|
||||||
|
|
||||||
|
res, err := http.Get(frontend.URL)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer res.Body.Close()
|
||||||
|
slurp, err := ioutil.ReadAll(res.Body)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if string(slurp) != "hi" {
|
||||||
|
t.Errorf("Got %q; want %q", slurp, "hi")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user