aboutsummaryrefslogtreecommitdiff
path: root/libgo/go/net/http/httputil/reverseproxy_test.go
diff options
context:
space:
mode:
Diffstat (limited to 'libgo/go/net/http/httputil/reverseproxy_test.go')
-rw-r--r--libgo/go/net/http/httputil/reverseproxy_test.go46
1 files changed, 43 insertions, 3 deletions
diff --git a/libgo/go/net/http/httputil/reverseproxy_test.go b/libgo/go/net/http/httputil/reverseproxy_test.go
index 3211463..4b6ad77 100644
--- a/libgo/go/net/http/httputil/reverseproxy_test.go
+++ b/libgo/go/net/http/httputil/reverseproxy_test.go
@@ -16,6 +16,7 @@ import (
"log"
"net/http"
"net/http/httptest"
+ "net/http/internal/ascii"
"net/url"
"os"
"reflect"
@@ -1121,6 +1122,45 @@ func TestReverseProxy_PanicBodyError(t *testing.T) {
rproxy.ServeHTTP(httptest.NewRecorder(), req)
}
+// Issue #46866: panic without closing incoming request body causes a panic
+func TestReverseProxy_PanicClosesIncomingBody(t *testing.T) {
+ backend := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ out := "this call was relayed by the reverse proxy"
+ // Coerce a wrong content length to induce io.ErrUnexpectedEOF
+ w.Header().Set("Content-Length", fmt.Sprintf("%d", len(out)*2))
+ fmt.Fprintln(w, out)
+ }))
+ defer backend.Close()
+ backendURL, err := url.Parse(backend.URL)
+ if err != nil {
+ t.Fatal(err)
+ }
+ proxyHandler := NewSingleHostReverseProxy(backendURL)
+ proxyHandler.ErrorLog = log.New(io.Discard, "", 0) // quiet for tests
+ frontend := httptest.NewServer(proxyHandler)
+ defer frontend.Close()
+ frontendClient := frontend.Client()
+
+ var wg sync.WaitGroup
+ for i := 0; i < 2; i++ {
+ wg.Add(1)
+ go func() {
+ defer wg.Done()
+ for j := 0; j < 10; j++ {
+ const reqLen = 6 * 1024 * 1024
+ req, _ := http.NewRequest("POST", frontend.URL, &io.LimitedReader{R: neverEnding('x'), N: reqLen})
+ req.ContentLength = reqLen
+ resp, _ := frontendClient.Transport.RoundTrip(req)
+ if resp != nil {
+ io.Copy(io.Discard, resp.Body)
+ resp.Body.Close()
+ }
+ }
+ }()
+ }
+ wg.Wait()
+}
+
func TestSelectFlushInterval(t *testing.T) {
tests := []struct {
name string
@@ -1242,7 +1282,7 @@ func TestReverseProxyWebSocket(t *testing.T) {
t.Errorf("Header(XHeader) = %q; want %q", got, want)
}
- if upgradeType(res.Header) != "websocket" {
+ if !ascii.EqualFold(upgradeType(res.Header), "websocket") {
t.Fatalf("not websocket upgrade; got %#v", res.Header)
}
rwc, ok := res.Body.(io.ReadWriteCloser)
@@ -1267,7 +1307,7 @@ func TestReverseProxyWebSocket(t *testing.T) {
}
}
-func TestReverseProxyWebSocketCancelation(t *testing.T) {
+func TestReverseProxyWebSocketCancellation(t *testing.T) {
n := 5
triggerCancelCh := make(chan bool, n)
nthResponse := func(i int) string {
@@ -1359,7 +1399,7 @@ func TestReverseProxyWebSocketCancelation(t *testing.T) {
t.Errorf("X-Header mismatch\n\tgot: %q\n\twant: %q", g, w)
}
- if g, w := upgradeType(res.Header), "websocket"; g != w {
+ if g, w := upgradeType(res.Header), "websocket"; !ascii.EqualFold(g, w) {
t.Fatalf("Upgrade header mismatch\n\tgot: %q\n\twant: %q", g, w)
}