Skip to content

Commit e07ce2f

Browse files
committed
Added persistent body on retry requests
1 parent 9359ab8 commit e07ce2f

File tree

3 files changed

+144
-59
lines changed

3 files changed

+144
-59
lines changed

client.go

+18
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package clink
22

33
import (
4+
"bytes"
45
"encoding/base64"
56
"encoding/json"
67
"fmt"
@@ -53,9 +54,26 @@ func (c *Client) Do(req *http.Request) (*http.Response, error) {
5354
}
5455

5556
var resp *http.Response
57+
var body []byte
5658
var err error
5759

60+
if req.Body != nil && req.Body != http.NoBody {
61+
body, err = io.ReadAll(req.Body)
62+
if err != nil {
63+
return nil, fmt.Errorf("failed to read request body: %w", err)
64+
}
65+
66+
err = req.Body.Close()
67+
if err != nil {
68+
return nil, fmt.Errorf("failed to close request body: %w", err)
69+
}
70+
}
71+
5872
for attempt := 0; attempt <= c.MaxRetries; attempt++ {
73+
if len(body) > 0 {
74+
req.Body = io.NopCloser(bytes.NewReader(body))
75+
}
76+
5977
resp, err = c.HttpClient.Do(req)
6078

6179
if req.Context().Err() != nil {

client_test.go

+61-1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"encoding/base64"
66
"encoding/json"
77
"errors"
8+
"fmt"
89
"io"
910
"net/http"
1011
"net/http/httptest"
@@ -347,7 +348,6 @@ func TestClient_Methods(t *testing.T) {
347348
if !tc.resultFunc(resp, tc.method) {
348349
t.Errorf("expected result to be successful")
349350
}
350-
351351
})
352352
}
353353
}
@@ -524,6 +524,66 @@ func TestUnsuccessfulRetries(t *testing.T) {
524524
}
525525
}
526526

527+
// TestRequestBodyEmptyOnRetries tests that the request body on a custom io.Reader wrapper is NOT empty on retries.
528+
type oneTimeReaderWrapper struct {
529+
data []byte
530+
consumed bool
531+
}
532+
533+
func (r *oneTimeReaderWrapper) Read(p []byte) (n int, err error) {
534+
if r.consumed {
535+
return 0, fmt.Errorf("body already read")
536+
}
537+
n = copy(p, r.data)
538+
r.consumed = true
539+
return n, io.EOF
540+
}
541+
542+
func TestRequestBodyNotEmptyOnRetries(t *testing.T) {
543+
var requestCount int
544+
var lastRequestBody string
545+
546+
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
547+
requestCount++
548+
549+
bodyBytes, err := io.ReadAll(r.Body)
550+
if err != nil {
551+
t.Fatalf("failed to read request body: %v", err)
552+
}
553+
lastRequestBody = string(bodyBytes)
554+
555+
w.WriteHeader(http.StatusInternalServerError)
556+
}))
557+
defer server.Close()
558+
559+
client := clink.NewClient(
560+
clink.WithRetries(1, func(request *http.Request, response *http.Response, err error) bool {
561+
return true
562+
}),
563+
clink.WithClient(server.Client()),
564+
)
565+
566+
requestBody := []byte("test body")
567+
req, err := http.NewRequest(http.MethodPost, server.URL, &oneTimeReaderWrapper{data: requestBody})
568+
if err != nil {
569+
t.Fatalf("failed to create request: %v", err)
570+
}
571+
572+
_, err = client.Do(req)
573+
if err != nil {
574+
t.Fatalf("failed to make request: %v", err)
575+
}
576+
577+
if requestCount != 2 {
578+
t.Fatalf("expected 2 requests due to retry, but got %d", requestCount)
579+
}
580+
581+
expectedBody := string(requestBody)
582+
if lastRequestBody != expectedBody {
583+
t.Errorf("expected request body to be '%s' on retry, got '%s'", expectedBody, lastRequestBody)
584+
}
585+
}
586+
527587
func TestContextCancellationDuringRetries(t *testing.T) {
528588
var requestCount int
529589
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {

coverage.out

+65-58
Original file line numberDiff line numberDiff line change
@@ -1,69 +1,76 @@
11
mode: count
2-
github.com/davesavic/clink/client.go:24.40,27.27 2 26
3-
github.com/davesavic/clink/client.go:27.27,29.3 1 31
4-
github.com/davesavic/clink/client.go:31.2,31.10 1 26
5-
github.com/davesavic/clink/client.go:34.30,39.2 1 26
6-
github.com/davesavic/clink/client.go:44.64,45.36 1 18
7-
github.com/davesavic/clink/client.go:45.36,47.3 1 2
8-
github.com/davesavic/clink/client.go:49.2,49.26 1 18
9-
github.com/davesavic/clink/client.go:49.26,50.59 1 2
10-
github.com/davesavic/clink/client.go:50.59,52.4 1 0
11-
github.com/davesavic/clink/client.go:55.2,58.55 3 18
12-
github.com/davesavic/clink/client.go:58.55,61.33 2 22
13-
github.com/davesavic/clink/client.go:61.33,63.4 1 1
14-
github.com/davesavic/clink/client.go:65.3,65.69 1 21
15-
github.com/davesavic/clink/client.go:65.69,66.9 1 1
16-
github.com/davesavic/clink/client.go:69.3,69.29 1 20
17-
github.com/davesavic/clink/client.go:69.29,70.11 1 5
18-
github.com/davesavic/clink/client.go:71.60,71.60 0 4
19-
github.com/davesavic/clink/client.go:72.32,73.36 1 1
20-
github.com/davesavic/clink/client.go:78.2,78.16 1 16
21-
github.com/davesavic/clink/client.go:78.16,80.3 1 0
22-
github.com/davesavic/clink/client.go:82.2,82.18 1 16
23-
github.com/davesavic/clink/client.go:86.59,88.16 2 1
24-
github.com/davesavic/clink/client.go:88.16,90.3 1 0
25-
github.com/davesavic/clink/client.go:91.2,91.18 1 1
26-
github.com/davesavic/clink/client.go:95.62,97.16 2 1
27-
github.com/davesavic/clink/client.go:97.16,99.3 1 0
28-
github.com/davesavic/clink/client.go:100.2,100.18 1 1
29-
github.com/davesavic/clink/client.go:104.58,106.16 2 1
2+
github.com/davesavic/clink/client.go:25.40,28.27 2 27
3+
github.com/davesavic/clink/client.go:28.27,30.3 1 33
4+
github.com/davesavic/clink/client.go:32.2,32.10 1 27
5+
github.com/davesavic/clink/client.go:35.30,40.2 1 27
6+
github.com/davesavic/clink/client.go:45.64,46.36 1 19
7+
github.com/davesavic/clink/client.go:46.36,48.3 1 2
8+
github.com/davesavic/clink/client.go:50.2,50.26 1 19
9+
github.com/davesavic/clink/client.go:50.26,51.59 1 2
10+
github.com/davesavic/clink/client.go:51.59,53.4 1 0
11+
github.com/davesavic/clink/client.go:56.2,60.48 4 19
12+
github.com/davesavic/clink/client.go:60.48,62.17 2 1
13+
github.com/davesavic/clink/client.go:62.17,64.4 1 0
14+
github.com/davesavic/clink/client.go:66.3,67.17 2 1
15+
github.com/davesavic/clink/client.go:67.17,69.4 1 0
16+
github.com/davesavic/clink/client.go:72.2,72.55 1 19
17+
github.com/davesavic/clink/client.go:72.55,73.20 1 24
18+
github.com/davesavic/clink/client.go:73.20,75.4 1 2
19+
github.com/davesavic/clink/client.go:77.3,79.33 2 24
20+
github.com/davesavic/clink/client.go:79.33,81.4 1 1
21+
github.com/davesavic/clink/client.go:83.3,83.69 1 23
22+
github.com/davesavic/clink/client.go:83.69,84.9 1 1
23+
github.com/davesavic/clink/client.go:87.3,87.29 1 22
24+
github.com/davesavic/clink/client.go:87.29,88.11 1 6
25+
github.com/davesavic/clink/client.go:89.60,89.60 0 5
26+
github.com/davesavic/clink/client.go:90.32,91.36 1 1
27+
github.com/davesavic/clink/client.go:96.2,96.16 1 17
28+
github.com/davesavic/clink/client.go:96.16,98.3 1 0
29+
github.com/davesavic/clink/client.go:100.2,100.18 1 17
30+
github.com/davesavic/clink/client.go:104.59,106.16 2 1
3031
github.com/davesavic/clink/client.go:106.16,108.3 1 0
3132
github.com/davesavic/clink/client.go:109.2,109.18 1 1
32-
github.com/davesavic/clink/client.go:113.75,115.16 2 1
33+
github.com/davesavic/clink/client.go:113.62,115.16 2 1
3334
github.com/davesavic/clink/client.go:115.16,117.3 1 0
3435
github.com/davesavic/clink/client.go:118.2,118.18 1 1
35-
github.com/davesavic/clink/client.go:122.74,124.16 2 1
36+
github.com/davesavic/clink/client.go:122.58,124.16 2 1
3637
github.com/davesavic/clink/client.go:124.16,126.3 1 0
3738
github.com/davesavic/clink/client.go:127.2,127.18 1 1
38-
github.com/davesavic/clink/client.go:131.76,133.16 2 1
39+
github.com/davesavic/clink/client.go:131.75,133.16 2 1
3940
github.com/davesavic/clink/client.go:133.16,135.3 1 0
4041
github.com/davesavic/clink/client.go:136.2,136.18 1 1
41-
github.com/davesavic/clink/client.go:140.61,142.16 2 1
42+
github.com/davesavic/clink/client.go:140.74,142.16 2 1
4243
github.com/davesavic/clink/client.go:142.16,144.3 1 0
4344
github.com/davesavic/clink/client.go:145.2,145.18 1 1
44-
github.com/davesavic/clink/client.go:151.45,152.25 1 18
45-
github.com/davesavic/clink/client.go:152.25,154.3 1 18
46-
github.com/davesavic/clink/client.go:158.43,159.25 1 2
47-
github.com/davesavic/clink/client.go:159.25,161.3 1 2
48-
github.com/davesavic/clink/client.go:165.52,166.25 1 2
49-
github.com/davesavic/clink/client.go:166.25,167.35 1 2
50-
github.com/davesavic/clink/client.go:167.35,169.4 1 2
51-
github.com/davesavic/clink/client.go:174.36,175.25 1 2
52-
github.com/davesavic/clink/client.go:175.25,178.3 2 2
53-
github.com/davesavic/clink/client.go:182.54,183.25 1 1
54-
github.com/davesavic/clink/client.go:183.25,187.3 3 1
55-
github.com/davesavic/clink/client.go:191.42,192.25 1 1
56-
github.com/davesavic/clink/client.go:192.25,194.3 1 1
57-
github.com/davesavic/clink/client.go:198.38,199.25 1 1
58-
github.com/davesavic/clink/client.go:199.25,201.3 1 1
59-
github.com/davesavic/clink/client.go:205.95,206.25 1 4
60-
github.com/davesavic/clink/client.go:206.25,209.3 2 4
61-
github.com/davesavic/clink/client.go:213.70,214.21 1 7
62-
github.com/davesavic/clink/client.go:214.21,216.3 1 1
63-
github.com/davesavic/clink/client.go:218.2,218.26 1 6
64-
github.com/davesavic/clink/client.go:218.26,220.3 1 1
65-
github.com/davesavic/clink/client.go:222.2,222.33 1 5
66-
github.com/davesavic/clink/client.go:222.33,224.3 1 5
67-
github.com/davesavic/clink/client.go:226.2,226.70 1 5
68-
github.com/davesavic/clink/client.go:226.70,228.3 1 1
69-
github.com/davesavic/clink/client.go:230.2,230.12 1 4
45+
github.com/davesavic/clink/client.go:149.76,151.16 2 1
46+
github.com/davesavic/clink/client.go:151.16,153.3 1 0
47+
github.com/davesavic/clink/client.go:154.2,154.18 1 1
48+
github.com/davesavic/clink/client.go:158.61,160.16 2 1
49+
github.com/davesavic/clink/client.go:160.16,162.3 1 0
50+
github.com/davesavic/clink/client.go:163.2,163.18 1 1
51+
github.com/davesavic/clink/client.go:169.45,170.25 1 19
52+
github.com/davesavic/clink/client.go:170.25,172.3 1 19
53+
github.com/davesavic/clink/client.go:176.43,177.25 1 2
54+
github.com/davesavic/clink/client.go:177.25,179.3 1 2
55+
github.com/davesavic/clink/client.go:183.52,184.25 1 2
56+
github.com/davesavic/clink/client.go:184.25,185.35 1 2
57+
github.com/davesavic/clink/client.go:185.35,187.4 1 2
58+
github.com/davesavic/clink/client.go:192.36,193.25 1 2
59+
github.com/davesavic/clink/client.go:193.25,196.3 2 2
60+
github.com/davesavic/clink/client.go:200.54,201.25 1 1
61+
github.com/davesavic/clink/client.go:201.25,205.3 3 1
62+
github.com/davesavic/clink/client.go:209.42,210.25 1 1
63+
github.com/davesavic/clink/client.go:210.25,212.3 1 1
64+
github.com/davesavic/clink/client.go:216.38,217.25 1 1
65+
github.com/davesavic/clink/client.go:217.25,219.3 1 1
66+
github.com/davesavic/clink/client.go:223.95,224.25 1 5
67+
github.com/davesavic/clink/client.go:224.25,227.3 2 5
68+
github.com/davesavic/clink/client.go:231.70,232.21 1 7
69+
github.com/davesavic/clink/client.go:232.21,234.3 1 1
70+
github.com/davesavic/clink/client.go:236.2,236.26 1 6
71+
github.com/davesavic/clink/client.go:236.26,238.3 1 1
72+
github.com/davesavic/clink/client.go:240.2,240.33 1 5
73+
github.com/davesavic/clink/client.go:240.33,242.3 1 5
74+
github.com/davesavic/clink/client.go:244.2,244.70 1 5
75+
github.com/davesavic/clink/client.go:244.70,246.3 1 1
76+
github.com/davesavic/clink/client.go:248.2,248.12 1 4

0 commit comments

Comments
 (0)