From 4e2c3fc7d85a6bbecf03c5b651dcd68b9126f954 Mon Sep 17 00:00:00 2001 From: Landry Benguigui Date: Fri, 21 Mar 2025 15:55:07 +0100 Subject: [PATCH] fix: ensure bufferWriter returns an error when exceeding maxResponseBodyBytes --- buffer/buffer.go | 22 ++++++++++++++-------- buffer/buffer_test.go | 8 ++++++-- 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/buffer/buffer.go b/buffer/buffer.go index 4c528228..cf312c87 100644 --- a/buffer/buffer.go +++ b/buffer/buffer.go @@ -164,6 +164,19 @@ func (b *Buffer) ServeHTTP(w http.ResponseWriter, req *http.Request) { outReq := b.copyRequest(req, body, totalSize) + defer func() { + if err := recover(); err != nil { + if err == http.ErrAbortHandler { + b.log.Error("vulcand/oxy/buffer: failed to read response, err: %v", err) + + b.errHandler.ServeHTTP(w, req, err.(error)) + return + } + + panic(err) + } + }() + attempt := 1 for { // We create a special writer that will limit the response size, buffer it to disk if necessary @@ -292,14 +305,7 @@ func (b *bufferWriter) Header() http.Header { } func (b *bufferWriter) Write(buf []byte) (int, error) { - length, err := b.buffer.Write(buf) - if err != nil { - // Since go1.11 (https://github.com/golang/go/commit/8f38f28222abccc505b9a1992deecfe3e2cb85de) - // if the writer returns an error, the reverse proxy panics - b.log.Error("write: %v", err) - length = len(buf) - } - return length, nil + return b.buffer.Write(buf) } // WriteHeader sets rw.Code. diff --git a/buffer/buffer_test.go b/buffer/buffer_test.go index 972692f3..e996553f 100644 --- a/buffer/buffer_test.go +++ b/buffer/buffer_test.go @@ -2,6 +2,7 @@ package buffer import ( "bufio" + "crypto/rand" "crypto/tls" "fmt" "io" @@ -173,8 +174,11 @@ func TestBuffer_requestLimitReached(t *testing.T) { } func TestBuffer_responseLimitReached(t *testing.T) { + payload := make([]byte, 40000) + _, _ = rand.Read(payload) + srv := testutils.NewHandler(func(w http.ResponseWriter, _ *http.Request) { - _, _ = w.Write([]byte("hello, this response is too large")) + _, _ = w.Write(payload) }) t.Cleanup(srv.Close) @@ -188,7 +192,7 @@ func TestBuffer_responseLimitReached(t *testing.T) { }) // stream handler will forward requests to redirect - st, err := New(rdr, MaxResponseBodyBytes(4)) + st, err := New(rdr, MaxResponseBodyBytes(10000)) require.NoError(t, err) proxy := httptest.NewServer(st)