components/golang/patches/0015-release-branch.go1.5-net-http-httputil-permit-nil-re.patch
changeset 5331 9c955076ffe3
equal deleted inserted replaced
5330:c36e3195e3e9 5331:9c955076ffe3
       
     1 From c0dd2011132f179e77f7f6e1ccd88b5a0e0ee659 Mon Sep 17 00:00:00 2001
       
     2 From: Brad Fitzpatrick <[email protected]>
       
     3 Date: Wed, 26 Aug 2015 10:53:59 -0700
       
     4 Subject: [PATCH 15/63] [release-branch.go1.5] net/http/httputil: permit nil
       
     5  request body in ReverseProxy
       
     6 
       
     7 Accepting a request with a nil body was never explicitly supported but
       
     8 happened to work in the past.
       
     9 
       
    10 This doesn't happen in most cases because usually people pass
       
    11 a Server's incoming Request to the ReverseProxy's ServeHTTP method,
       
    12 and incoming server requests are guaranteed to have non-nil bodies.
       
    13 
       
    14 Still, it's a regression, so fix.
       
    15 
       
    16 Fixes #12344
       
    17 
       
    18 Change-Id: Id9a5a47aea3f2875d195b66c9a5f8581c4ca2aed
       
    19 Reviewed-on: https://go-review.googlesource.com/13935
       
    20 Reviewed-by: Ian Lance Taylor <[email protected]>
       
    21 Run-TryBot: Brad Fitzpatrick <[email protected]>
       
    22 TryBot-Result: Gobot Gobot <[email protected]>
       
    23 Reviewed-on: https://go-review.googlesource.com/14245
       
    24 ---
       
    25  src/net/http/httputil/reverseproxy.go      |  5 +++-
       
    26  src/net/http/httputil/reverseproxy_test.go | 39 ++++++++++++++++++++++++++++++
       
    27  2 files changed, 43 insertions(+), 1 deletion(-)
       
    28 
       
    29 diff --git a/src/net/http/httputil/reverseproxy.go b/src/net/http/httputil/reverseproxy.go
       
    30 index 3b7a184..c8e1132 100644
       
    31 --- a/src/net/http/httputil/reverseproxy.go
       
    32 +++ b/src/net/http/httputil/reverseproxy.go
       
    33 @@ -105,7 +105,7 @@ type requestCanceler interface {
       
    34  }
       
    35  
       
    36  type runOnFirstRead struct {
       
    37 -	io.Reader
       
    38 +	io.Reader // optional; nil means empty body
       
    39  
       
    40  	fn func() // Run before first Read, then set to nil
       
    41  }
       
    42 @@ -115,6 +115,9 @@ func (c *runOnFirstRead) Read(bs []byte) (int, error) {
       
    43  		c.fn()
       
    44  		c.fn = nil
       
    45  	}
       
    46 +	if c.Reader == nil {
       
    47 +		return 0, io.EOF
       
    48 +	}
       
    49  	return c.Reader.Read(bs)
       
    50  }
       
    51  
       
    52 diff --git a/src/net/http/httputil/reverseproxy_test.go b/src/net/http/httputil/reverseproxy_test.go
       
    53 index 25947e6..80a26ab 100644
       
    54 --- a/src/net/http/httputil/reverseproxy_test.go
       
    55 +++ b/src/net/http/httputil/reverseproxy_test.go
       
    56 @@ -7,6 +7,7 @@
       
    57  package httputil
       
    58  
       
    59  import (
       
    60 +	"bufio"
       
    61  	"io/ioutil"
       
    62  	"log"
       
    63  	"net/http"
       
    64 @@ -281,3 +282,41 @@ func TestReverseProxyCancellation(t *testing.T) {
       
    65  		t.Fatal("DefaultClient.Do() returned nil error")
       
    66  	}
       
    67  }
       
    68 +
       
    69 +func req(t *testing.T, v string) *http.Request {
       
    70 +	req, err := http.ReadRequest(bufio.NewReader(strings.NewReader(v)))
       
    71 +	if err != nil {
       
    72 +		t.Fatal(err)
       
    73 +	}
       
    74 +	return req
       
    75 +}
       
    76 +
       
    77 +// Issue 12344
       
    78 +func TestNilBody(t *testing.T) {
       
    79 +	backend := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
       
    80 +		w.Write([]byte("hi"))
       
    81 +	}))
       
    82 +	defer backend.Close()
       
    83 +
       
    84 +	frontend := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
       
    85 +		backURL, _ := url.Parse(backend.URL)
       
    86 +		rp := NewSingleHostReverseProxy(backURL)
       
    87 +		r := req(t, "GET / HTTP/1.0\r\n\r\n")
       
    88 +		r.Body = nil // this accidentally worked in Go 1.4 and below, so keep it working
       
    89 +		rp.ServeHTTP(w, r)
       
    90 +	}))
       
    91 +	defer frontend.Close()
       
    92 +
       
    93 +	res, err := http.Get(frontend.URL)
       
    94 +	if err != nil {
       
    95 +		t.Fatal(err)
       
    96 +	}
       
    97 +	defer res.Body.Close()
       
    98 +	slurp, err := ioutil.ReadAll(res.Body)
       
    99 +	if err != nil {
       
   100 +		t.Fatal(err)
       
   101 +	}
       
   102 +	if string(slurp) != "hi" {
       
   103 +		t.Errorf("Got %q; want %q", slurp, "hi")
       
   104 +	}
       
   105 +}
       
   106 -- 
       
   107 2.6.1
       
   108