Skip to content

Commit

Permalink
fix: buffer reset issue in io.Reader with content length enabled #917
Browse files Browse the repository at this point in the history
  • Loading branch information
jeevatkm committed Nov 20, 2024
1 parent feedf18 commit 67cf80b
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 2 deletions.
39 changes: 39 additions & 0 deletions request_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,13 @@ import (
"io"
"net"
"net/http"
"net/http/httptest"
"net/url"
"os"
"path/filepath"
"strconv"
"strings"
"sync"
"testing"
"time"

Expand Down Expand Up @@ -2195,3 +2197,40 @@ func TestSetResultMustNotPanicOnNil(t *testing.T) {
}()
dc().R().SetResult(nil)
}

func TestRequestGH917(t *testing.T) {
// Mock server returns 500 status code to cause client retries.
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
b, err := io.ReadAll(r.Body)
assertError(t, err)
if len(b) > 0 {
// sometimes, the body is "testtest" instead of "test"
assertEqual(t, "test", string(b))
}
w.WriteHeader(http.StatusInternalServerError)
}))

client := New().AddRetryCondition(
func(r *Response, err error) bool {
return err != nil || r.StatusCode() > 499
},
).SetRetryCount(3)

wg := sync.WaitGroup{}
// Run tests concurrently to make the issue easily to observe.
for i := 0; i < 100; i++ {
wg.Add(1)
go func() {
defer wg.Done()
for j := 0; j < 10; j++ {
buf := bytes.NewBufferString("test")
// Trigger some retries
resp, err := client.R().SetBody(buf).SetContentLength(true).Execute(http.MethodPost, srv.URL)
assertNil(t, err)
assertEqual(t, http.StatusInternalServerError, resp.StatusCode())
assertEqual(t, "", string(resp.Body()))
}
}()
}
wg.Wait()
}
9 changes: 7 additions & 2 deletions util.go
Original file line number Diff line number Diff line change
Expand Up @@ -286,12 +286,17 @@ func functionName(i interface{}) string {
}

func acquireBuffer() *bytes.Buffer {
return bufPool.Get().(*bytes.Buffer)
buf := bufPool.Get().(*bytes.Buffer)
if buf.Len() == 0 {
buf.Reset()
return buf
}
bufPool.Put(buf)
return new(bytes.Buffer)
}

func releaseBuffer(buf *bytes.Buffer) {
if buf != nil {
buf.Reset()
bufPool.Put(buf)
}
}
Expand Down

0 comments on commit 67cf80b

Please sign in to comment.