Skip to content

Commit 63ec989

Browse files
authored
fix: large memory usage on detail logging post requests (#5039)
1 parent bf75027 commit 63ec989

File tree

2 files changed

+27
-3
lines changed

2 files changed

+27
-3
lines changed

rest/handler/loghandler.go

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,9 @@ import (
2424
)
2525

2626
const (
27-
limitBodyBytes = 1024
28-
defaultSlowThreshold = time.Millisecond * 500
27+
limitBodyBytes = 1024
28+
limitDetailedBodyBytes = 4096
29+
defaultSlowThreshold = time.Millisecond * 500
2930
)
3031

3132
var slowThreshold = syncx.ForAtomicDuration(defaultSlowThreshold)
@@ -94,7 +95,8 @@ func DetailedLogHandler(next http.Handler) http.Handler {
9495
lrw := newDetailLoggedResponseWriter(rw, &buf)
9596

9697
var dup io.ReadCloser
97-
r.Body, dup = iox.DupReadCloser(r.Body)
98+
// https://github.com/zeromicro/go-zero/issues/3564
99+
r.Body, dup = iox.LimitDupReadCloser(r.Body, limitDetailedBodyBytes)
98100
logs := new(internal.LogCollector)
99101
next.ServeHTTP(lrw, r.WithContext(internal.WithLogCollector(r.Context(), logs)))
100102
r.Body = dup

rest/handler/loghandler_test.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"time"
1111

1212
"github.com/stretchr/testify/assert"
13+
"github.com/zeromicro/go-zero/core/logx/logtest"
1314
"github.com/zeromicro/go-zero/rest/internal"
1415
"github.com/zeromicro/go-zero/rest/internal/response"
1516
)
@@ -86,6 +87,26 @@ func TestLogHandlerSlow(t *testing.T) {
8687
assert.Equal(t, http.StatusOK, resp.Code)
8788
}
8889
}
90+
91+
func TestDetailedLogHandler_LargeBody(t *testing.T) {
92+
lbuf := logtest.NewCollector(t)
93+
94+
var buf bytes.Buffer
95+
for i := 0; i < limitDetailedBodyBytes<<2; i++ {
96+
buf.WriteByte('a')
97+
}
98+
99+
req := httptest.NewRequest(http.MethodPost, "http://localhost", &buf)
100+
h := DetailedLogHandler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
101+
io.Copy(io.Discard, r.Body)
102+
}))
103+
resp := httptest.NewRecorder()
104+
h.ServeHTTP(resp, req)
105+
106+
// extra 200 for the length of POST request headers
107+
assert.True(t, len(lbuf.Content()) < limitDetailedBodyBytes+200)
108+
}
109+
89110
func TestDetailedLogHandler_Hijack(t *testing.T) {
90111
resp := httptest.NewRecorder()
91112
writer := &detailLoggedResponseWriter{
@@ -111,6 +132,7 @@ func TestDetailedLogHandler_Hijack(t *testing.T) {
111132
_, _, _ = writer.Hijack()
112133
})
113134
}
135+
114136
func TestSetSlowThreshold(t *testing.T) {
115137
assert.Equal(t, defaultSlowThreshold, slowThreshold.Load())
116138
SetSlowThreshold(time.Second)

0 commit comments

Comments
 (0)