Skip to content

Commit 19a97c8

Browse files
authored
buffer: handle bufferWriter error (#247)
1 parent c522a25 commit 19a97c8

File tree

2 files changed

+78
-24
lines changed

2 files changed

+78
-24
lines changed

buffer/buffer.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,12 @@ func (b *Buffer) ServeHTTP(w http.ResponseWriter, req *http.Request) {
189189
return
190190
}
191191

192+
if bw.writeError != nil {
193+
b.log.Error("vulcand/oxy/buffer: failed to copy response, err: %v", bw.writeError)
194+
b.errHandler.ServeHTTP(w, req, bw.writeError)
195+
return
196+
}
197+
192198
var reader multibuf.MultiReader
193199
if bw.expectBody(outReq) {
194200
rdr, err := writer.Reader()
@@ -258,6 +264,7 @@ type bufferWriter struct {
258264
buffer multibuf.WriterOnce
259265
responseWriter http.ResponseWriter
260266
hijacked bool
267+
writeError error
261268
log utils.Logger
262269
}
263270

@@ -298,6 +305,7 @@ func (b *bufferWriter) Write(buf []byte) (int, error) {
298305
// if the writer returns an error, the reverse proxy panics
299306
b.log.Error("write: %v", err)
300307
length = len(buf)
308+
b.writeError = err
301309
}
302310
return length, nil
303311
}

buffer/buffer_test.go

Lines changed: 70 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"net/http"
1010
"net/http/httptest"
1111
"strconv"
12+
"strings"
1213
"testing"
1314

1415
"github.com/stretchr/testify/assert"
@@ -173,30 +174,75 @@ func TestBuffer_requestLimitReached(t *testing.T) {
173174
}
174175

175176
func TestBuffer_responseLimitReached(t *testing.T) {
176-
srv := testutils.NewHandler(func(w http.ResponseWriter, _ *http.Request) {
177-
_, _ = w.Write([]byte("hello, this response is too large"))
178-
})
179-
t.Cleanup(srv.Close)
180-
181-
// forwarder will proxy the request to whatever destination
182-
fwd := forward.New(false)
183-
184-
// this is our redirect to server
185-
rdr := http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
186-
req.URL = testutils.MustParseRequestURI(srv.URL)
187-
fwd.ServeHTTP(w, req)
188-
})
189-
190-
// stream handler will forward requests to redirect
191-
st, err := New(rdr, MaxResponseBodyBytes(4))
192-
require.NoError(t, err)
193-
194-
proxy := httptest.NewServer(st)
195-
t.Cleanup(proxy.Close)
196-
197-
re, _, err := testutils.Get(proxy.URL)
198-
require.NoError(t, err)
199-
assert.Equal(t, http.StatusInternalServerError, re.StatusCode)
177+
cases := []struct {
178+
name string
179+
body string
180+
maxResponseBodyBytes int64
181+
}{
182+
{
183+
name: "small limit with body larger than max response bytes",
184+
body: "hello, this response is too large",
185+
maxResponseBodyBytes: 4,
186+
},
187+
{
188+
name: "small limit with body larger than 32768 bytes",
189+
body: strings.Repeat("A", 32769),
190+
maxResponseBodyBytes: 4,
191+
},
192+
{
193+
name: "larger limit with body larger than 32768 bytes",
194+
body: strings.Repeat("A", 32769),
195+
maxResponseBodyBytes: 2000,
196+
},
197+
{
198+
name: "larger limit with body larger than 32768 + 1999 bytes",
199+
body: strings.Repeat("A", 32769+1999),
200+
maxResponseBodyBytes: 2000,
201+
},
202+
{
203+
name: "larger limit with body larger than 32768 + 2000 bytes",
204+
body: strings.Repeat("A", 32769+2000),
205+
maxResponseBodyBytes: 2000,
206+
},
207+
{
208+
name: "larger limit with body larger than 65536 + 1999 bytes",
209+
body: strings.Repeat("A", 65537+1999),
210+
maxResponseBodyBytes: 2000,
211+
},
212+
{
213+
name: "larger limit with body larger than 65536 + 2000 bytes",
214+
body: strings.Repeat("A", 65537+2000),
215+
maxResponseBodyBytes: 2000,
216+
},
217+
}
218+
for _, tc := range cases {
219+
t.Run(tc.name, func(t *testing.T) {
220+
srv := testutils.NewHandler(func(w http.ResponseWriter, _ *http.Request) {
221+
_, _ = w.Write([]byte(tc.body))
222+
})
223+
t.Cleanup(srv.Close)
224+
225+
// forwarder will proxy the request to whatever destination
226+
fwd := forward.New(false)
227+
228+
// this is our redirect to server
229+
rdr := http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
230+
req.URL = testutils.MustParseRequestURI(srv.URL)
231+
fwd.ServeHTTP(w, req)
232+
})
233+
234+
// stream handler will forward requests to redirect
235+
st, err := New(rdr, MaxResponseBodyBytes(tc.maxResponseBodyBytes))
236+
require.NoError(t, err)
237+
238+
proxy := httptest.NewServer(st)
239+
t.Cleanup(proxy.Close)
240+
241+
re, _, err := testutils.Get(proxy.URL)
242+
require.NoError(t, err)
243+
assert.Equal(t, http.StatusInternalServerError, re.StatusCode)
244+
})
245+
}
200246
}
201247

202248
func TestBuffer_fileStreamingResponse(t *testing.T) {

0 commit comments

Comments
 (0)