diff --git a/README.md b/README.md index 2bc0508..e513b24 100644 --- a/README.md +++ b/README.md @@ -4,12 +4,12 @@
Features section describes in detail about Resty capabilities
-
+ ## News - * v2.16.0 [released](https://github.com/go-resty/resty/releases/tag/v2.16.0) and tagged on Nov 10, 2024. + * v2.16.1 [released](https://github.com/go-resty/resty/releases/tag/v2.16.1) and tagged on Nov 19, 2024. * v2.0.0 [released](https://github.com/go-resty/resty/releases/tag/v2.0.0) and tagged on Jul 16, 2019. * v1.12.0 [released](https://github.com/go-resty/resty/releases/tag/v1.12.0) and tagged on Feb 27, 2019. * v1.0 released and tagged on Sep 25, 2017. - Resty's first version was released on Sep 15, 2015 then it grew gradually as a very handy and helpful library. Its been a two years since first release. I'm very thankful to Resty users and its [contributors](https://github.com/go-resty/resty/graphs/contributors). @@ -105,7 +105,7 @@ Resty author also published following projects for Go Community. ```bash # Go Modules -require github.com/go-resty/resty/v2 v2.16.0 +require github.com/go-resty/resty/v2 v2.16.1 ``` ## Usage diff --git a/request_test.go b/request_test.go index 44bec45..2d1e5bf 100644 --- a/request_test.go +++ b/request_test.go @@ -12,11 +12,13 @@ import ( "io" "net" "net/http" + "net/http/httptest" "net/url" "os" "path/filepath" "strconv" "strings" + "sync" "testing" "time" @@ -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() +} diff --git a/resty.go b/resty.go index 19f95ad..450aa66 100644 --- a/resty.go +++ b/resty.go @@ -14,7 +14,7 @@ import ( ) // Version # of resty -const Version = "2.16.0" +const Version = "2.16.1" // New method creates a new Resty client. func New() *Client { diff --git a/util.go b/util.go index e1a66ff..9f58a3f 100644 --- a/util.go +++ b/util.go @@ -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) } }