Skip to content

Commit 386974e

Browse files
authored
fix: executeWithRetry, save the request body and write the body to th… (#296)
* fix: executeWithRetry, save the request body and write the body to the request before we process it * fix request body after reading it * close the request body, not using defer since we update the request body in an infinite loop * fix test
1 parent cdea70f commit 386974e

File tree

2 files changed

+44
-5
lines changed

2 files changed

+44
-5
lines changed

proxy.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"errors"
77
"fmt"
88
"io"
9+
"io/ioutil"
910
"net"
1011
"net/http"
1112
"net/http/httputil"
@@ -197,8 +198,21 @@ func executeWithRetry(
197198
startTime := time.Now()
198199
var since float64
199200

201+
// keep the request body
202+
body, err := ioutil.ReadAll(req.Body)
203+
req.Body.Close()
204+
if err != nil {
205+
since = time.Since(startTime).Seconds()
206+
207+
return since, err
208+
}
209+
200210
numRetry := 0
201211
for {
212+
// update body
213+
req.Body = ioutil.NopCloser(bytes.NewBuffer(body))
214+
req.Body.Close()
215+
202216
rp(rw, req)
203217

204218
err := ctx.Err()

proxyretry_test.go

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,11 @@ package main
33
import (
44
"context"
55
"fmt"
6+
"io/ioutil"
67
"net/http"
78
"net/http/httptest"
89
"net/url"
10+
"strings"
911
"testing"
1012
"time"
1113

@@ -25,16 +27,22 @@ type mockStatResponseWriter struct {
2527
}
2628

2729
type mockHosts struct {
30+
t *testing.T
31+
b string
2832
hs []string
2933
hst []string
3034
}
3135

3236
// TestQueryWithRetryFail function statResponseWriter's statusCode will not be 200, but the query has been proxied
3337
// The request will be retried 1 time with a different host in the same replica
3438
func TestQueryWithRetryFail(t *testing.T) {
35-
req := newRequest("http://localhost:8080")
39+
body := "foo query"
40+
41+
req := newRequest("http://localhost:8080", body)
3642

3743
mhs := &mockHosts{
44+
t: t,
45+
b: body,
3846
hs: []string{"localhost:8080", "localhost:8081"},
3947
}
4048

@@ -71,9 +79,13 @@ func TestQueryWithRetryFail(t *testing.T) {
7179
// TestRunQuerySuccessOnce function statResponseWriter's statusCode will be StatusOK after executeWithRetry, the query has been proxied
7280
// The execution will succeeded without retry
7381
func TestQuerySuccessOnce(t *testing.T) {
74-
req := newRequest("http://localhost:8090")
82+
body := "foo query"
83+
84+
req := newRequest("http://localhost:8090", body)
7585

7686
mhs := &mockHosts{
87+
t: t,
88+
b: body,
7789
hs: []string{"localhost:8080", "localhost:8090"},
7890
}
7991

@@ -108,9 +120,13 @@ func TestQuerySuccessOnce(t *testing.T) {
108120
// TestQueryWithRetrySuccess function statResponseWriter's statusCode will be StatusOK after executeWithRetry, the query has been proxied
109121
// The execution will succeeded after retry
110122
func TestQueryWithRetrySuccess(t *testing.T) {
111-
req := newRequest("http://localhost:8080")
123+
body := "foo query"
124+
125+
req := newRequest("http://localhost:8080", body)
112126

113127
mhs := &mockHosts{
128+
t: t,
129+
b: body,
114130
hs: []string{"localhost:8080", "localhost:8090"},
115131
}
116132

@@ -148,12 +164,21 @@ func (mhs *mockHosts) mockReverseProxy(rw http.ResponseWriter, req *http.Request
148164
} else {
149165
rw.WriteHeader(http.StatusOK)
150166
}
167+
168+
b, err := ioutil.ReadAll(req.Body)
169+
if err != nil {
170+
mhs.t.Errorf("The req body cannot be read: %v", err)
171+
}
172+
req.Body.Close()
173+
174+
assert.Equal(mhs.t, mhs.b, string(b))
175+
151176
mhs.hst = append(mhs.hst, req.URL.Host)
152177
}
153178

154-
func newRequest(host string) *http.Request {
179+
func newRequest(host, body string) *http.Request {
155180
// create a new req
156-
req := httptest.NewRequest(http.MethodGet, host, nil)
181+
req := httptest.NewRequest(http.MethodPost, host, strings.NewReader(body))
157182

158183
ctx := context.Background()
159184

0 commit comments

Comments
 (0)