diff options
author | Brad Fitzpatrick <bradfitz@golang.org> | 2016-01-04 20:38:20 +0000 |
---|---|---|
committer | Brad Fitzpatrick <bradfitz@golang.org> | 2016-01-05 04:39:11 +0000 |
commit | 4b0bc7c3a14ac446bc13d22098de8db382205401 (patch) | |
tree | bb2b2639674f6de7230d3116aaf5296c56b24d66 /src/net/http/httputil/reverseproxy_test.go | |
parent | 66f1f89dc058e98d4b118041cd8d571a505b43db (diff) | |
download | go-4b0bc7c3a14ac446bc13d22098de8db382205401.tar.gz go-4b0bc7c3a14ac446bc13d22098de8db382205401.zip |
net/http: relax recently-updated rules and behavior of CloseNotifier
The CloseNotifier implementation and documentation was
substantially changed in https://golang.org/cl/17750 but it was a bit
too aggressive.
Issue #13666 highlighted that in addition to breaking external
projects, even the standard library (httputil.ReverseProxy) didn't
obey the new rules about not using CloseNotifier until the
Request.Body is fully consumed.
So, instead of fixing httputil.ReverseProxy, dial back the rules a
bit. It's now okay to call CloseNotify before consuming the request
body. The docs now say CloseNotifier may wait to fire before the
request body is fully consumed, but doesn't say that the behavior is
undefined anymore. Instead, we just wait until the request body is
consumed and start watching for EOF from the client then.
This CL also adds a test to ReverseProxy (using a POST request) that
would've caught this earlier.
Fixes #13666
Change-Id: Ib4e8c29c4bfbe7511f591cf9ffcda23a0f0b1269
Reviewed-on: https://go-review.googlesource.com/18144
Reviewed-by: Russ Cox <rsc@golang.org>
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
Diffstat (limited to 'src/net/http/httputil/reverseproxy_test.go')
-rw-r--r-- | src/net/http/httputil/reverseproxy_test.go | 42 |
1 files changed, 41 insertions, 1 deletions
diff --git a/src/net/http/httputil/reverseproxy_test.go b/src/net/http/httputil/reverseproxy_test.go index 5f6fc56e07..a944e8e0f5 100644 --- a/src/net/http/httputil/reverseproxy_test.go +++ b/src/net/http/httputil/reverseproxy_test.go @@ -8,6 +8,7 @@ package httputil import ( "bufio" + "bytes" "io" "io/ioutil" "log" @@ -104,7 +105,6 @@ func TestReverseProxy(t *testing.T) { if g, e := res.Trailer.Get("X-Trailer"), "trailer_value"; g != e { t.Errorf("Trailer(X-Trailer) = %q ; want %q", g, e) } - } func TestXForwardedFor(t *testing.T) { @@ -384,3 +384,43 @@ func TestReverseProxyGetPutBuffer(t *testing.T) { t.Errorf("Log events = %q; want %q", log, wantLog) } } + +func TestReverseProxy_Post(t *testing.T) { + const backendResponse = "I am the backend" + const backendStatus = 200 + var requestBody = bytes.Repeat([]byte("a"), 1<<20) + backend := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + slurp, err := ioutil.ReadAll(r.Body) + if err != nil { + t.Error("Backend body read = %v", err) + } + if len(slurp) != len(requestBody) { + t.Errorf("Backend read %d request body bytes; want %d", len(slurp), len(requestBody)) + } + if !bytes.Equal(slurp, requestBody) { + t.Error("Backend read wrong request body.") // 1MB; omitting details + } + w.Write([]byte(backendResponse)) + })) + defer backend.Close() + backendURL, err := url.Parse(backend.URL) + if err != nil { + t.Fatal(err) + } + proxyHandler := NewSingleHostReverseProxy(backendURL) + frontend := httptest.NewServer(proxyHandler) + defer frontend.Close() + + postReq, _ := http.NewRequest("POST", frontend.URL, bytes.NewReader(requestBody)) + res, err := http.DefaultClient.Do(postReq) + if err != nil { + t.Fatalf("Do: %v", err) + } + if g, e := res.StatusCode, backendStatus; g != e { + t.Errorf("got res.StatusCode %d; expected %d", g, e) + } + bodyBytes, _ := ioutil.ReadAll(res.Body) + if g, e := string(bodyBytes), backendResponse; g != e { + t.Errorf("got body %q; expected %q", g, e) + } +} |