Skip to content

Commit 26898b0

Browse files
authored
fix: Retry on NGINX LB errors (#273)
* Retry on NGINX LB errors * use HTML * go fumpt
1 parent 7dcc21b commit 26898b0

File tree

3 files changed

+47
-0
lines changed

3 files changed

+47
-0
lines changed

client.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,7 @@ func (c *Client) SetRetries() *Client {
239239
addRetryConditional(tooManyRequestsRetryCondition).
240240
addRetryConditional(serviceUnavailableRetryCondition).
241241
addRetryConditional(requestTimeoutRetryCondition).
242+
addRetryConditional(requestNGINXRetryCondition).
242243
SetRetryMaxWaitTime(APIRetryMaxWaitTime)
243244
configureRetries(c)
244245
return c

retries.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,12 @@ func requestTimeoutRetryCondition(r *resty.Response, _ error) bool {
7474
return r.StatusCode() == http.StatusRequestTimeout
7575
}
7676

77+
func requestNGINXRetryCondition(r *resty.Response, _ error) bool {
78+
return r.StatusCode() == http.StatusBadRequest &&
79+
r.Header().Get("Server") == "nginx" &&
80+
r.Header().Get("Content-Type") == "text/html"
81+
}
82+
7783
func respectRetryAfter(client *resty.Client, resp *resty.Response) (time.Duration, error) {
7884
retryAfterStr := resp.Header().Get(retryAfterHeaderName)
7985
if retryAfterStr == "" {

test/integration/client_test.go

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
package integration
22

33
import (
4+
"context"
5+
"github.com/jarcoal/httpmock"
6+
"github.com/linode/linodego"
7+
"net/http"
48
"testing"
59
)
610

@@ -26,3 +30,39 @@ func TestClient_Aliases(t *testing.T) {
2630
t.Error("Expected alias for Volumes to return a *Resource")
2731
}
2832
}
33+
34+
func TestClient_NGINXRetry(t *testing.T) {
35+
client := createMockClient(t)
36+
37+
// Recreate the NGINX LB error
38+
nginxErrorFunc := func(request *http.Request) (*http.Response, error) {
39+
resp := httpmock.NewStringResponse(400, "")
40+
41+
resp.Header.Add("Server", "nginx")
42+
resp.Header.Set("Content-Type", "text/html")
43+
44+
return resp, nil
45+
}
46+
47+
step := 0
48+
49+
httpmock.RegisterRegexpResponder("PUT",
50+
mockRequestURL(t, "/profile"), func(request *http.Request) (*http.Response, error) {
51+
if step == 0 {
52+
step++
53+
return nginxErrorFunc(request)
54+
}
55+
56+
step++
57+
return httpmock.NewJsonResponse(200, nil)
58+
})
59+
60+
if _, err := client.UpdateProfile(context.Background(),
61+
linodego.ProfileUpdateOptions{}); err != nil {
62+
t.Fatal(err)
63+
}
64+
65+
if step != 2 {
66+
t.Fatalf("retry checks did not finish")
67+
}
68+
}

0 commit comments

Comments
 (0)