Skip to content

Commit 5724808

Browse files
authored
Custom Error Type for Handling HTTP Error Codes (#62)
Signed-off-by: aanujj <anujkrishankant@gmail.com>
1 parent b2165d8 commit 5724808

File tree

7 files changed

+95
-27
lines changed

7 files changed

+95
-27
lines changed

.golangci.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,11 @@ issues:
2828
- gosec
2929
- unparam
3030
- wsl
31+
- revive
32+
- path: '(.+)_test.go'
33+
linters:
34+
- revive
35+
text: "dot-imports: should not use dot imports"
3136
# maximum count of issues with the same text. set to 0 to disable. default is 3.
3237
max-same-issues: 0
3338
linters-settings:

.travis.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ language: go
33
os: linux
44
dist: focal
55
go:
6-
- "1.18.6"
6+
- "1.20.14"
77

88
before_install:
99
- pip --quiet install yamllint

fluent/client/errors.go

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
package client
2+
3+
import (
4+
"fmt"
5+
"net/http"
6+
)
7+
8+
type WSConnError struct {
9+
StatusCode int
10+
ResponseBody string
11+
ConnErr error
12+
retryable bool
13+
}
14+
15+
var nonRetryableStatusCodes = []int{
16+
http.StatusBadRequest,
17+
http.StatusUnauthorized,
18+
http.StatusForbidden,
19+
http.StatusNotFound,
20+
http.StatusMethodNotAllowed,
21+
http.StatusNotImplemented,
22+
http.StatusHTTPVersionNotSupported,
23+
}
24+
25+
func (e *WSConnError) Error() string {
26+
if e.ConnErr != nil {
27+
return fmt.Sprintf("Connection Error %s. Status Code: %d. Response: %s", e.ConnErr.Error(), e.StatusCode, e.ResponseBody)
28+
}
29+
30+
return fmt.Sprintf("Connection Error. Status Code: %d. Response: %s", e.StatusCode, e.ResponseBody)
31+
}
32+
33+
func (e *WSConnError) IsRetryable() bool {
34+
return e.retryable
35+
}
36+
37+
func NewWSConnError(err error, statusCode int, respBody string) *WSConnError {
38+
return &WSConnError{ConnErr: err,
39+
StatusCode: statusCode,
40+
ResponseBody: respBody,
41+
retryable: isRetryableStatusCode(statusCode),
42+
}
43+
}
44+
45+
// isRetryableStatusCode checks if the provided HTTP status code is retryable
46+
func isRetryableStatusCode(statusCode int) bool {
47+
for _, nonRetryableCode := range nonRetryableStatusCodes {
48+
if statusCode == nonRetryableCode {
49+
return false
50+
}
51+
}
52+
53+
return true
54+
}

fluent/client/ws_client.go

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,8 @@ import (
2828
"bytes"
2929
"crypto/tls"
3030
"errors"
31-
"fmt"
3231
"io"
3332
"net/http"
34-
"strconv"
3533
"sync"
3634

3735
"github.com/IBM/fluent-forward-go/fluent/client/ws"
@@ -115,15 +113,16 @@ func (wcf *DefaultWSConnectionFactory) New() (ext.Conn, error) {
115113

116114
conn, resp, err := dialer.Dial(wcf.URL, header)
117115
if resp != nil && resp.Body != nil {
116+
defer resp.Body.Close()
117+
118118
bodyBytes, readErr := io.ReadAll(resp.Body)
119-
if readErr == nil {
120-
bodyString := string(bodyBytes)
121-
if resp.StatusCode >= 300 {
122-
err = fmt.Errorf("%s. %s:%s", err, strconv.Itoa(resp.StatusCode), bodyString)
123-
}
119+
if readErr != nil {
120+
err = readErr
124121
}
125122

126-
resp.Body.Close()
123+
if resp.StatusCode >= 300 {
124+
err = NewWSConnError(err, resp.StatusCode, string(bodyBytes))
125+
}
127126
}
128127

129128
return conn, err

fluent/client/ws_client_test.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ var _ = Describe("DefaultWSConnectionFactory", func() {
6464
svr *httptest.Server
6565
ch chan struct{}
6666
useTLS, testError bool
67+
customErr *client.WSConnError
6768
)
6869

6970
happyHandler := func(ch chan struct{}) http.Handler {
@@ -151,7 +152,12 @@ var _ = Describe("DefaultWSConnectionFactory", func() {
151152

152153
err := cli.Connect()
153154
Expect(err).To(HaveOccurred())
154-
Expect(err.Error()).To(ContainSubstring("websocket: bad handshake. 500:broken test"))
155+
156+
Expect(errors.As(err, &customErr)).To(BeTrue())
157+
Expect(customErr.StatusCode).To(Equal(http.StatusInternalServerError))
158+
Expect(customErr.ConnErr.Error()).To(ContainSubstring("websocket: bad handshake"))
159+
Expect(customErr.ResponseBody).To(ContainSubstring("broken test"))
160+
Expect(customErr.IsRetryable()).To(BeTrue())
155161
})
156162

157163
})

go.mod

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,15 @@ require (
1818
github.com/davecgh/go-spew v1.1.1 // indirect
1919
github.com/go-logr/logr v1.2.4 // indirect
2020
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect
21-
github.com/google/go-cmp v0.5.9 // indirect
21+
github.com/google/go-cmp v0.6.0 // indirect
2222
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 // indirect
2323
github.com/kr/pretty v0.3.1 // indirect
2424
github.com/philhofer/fwd v1.1.2 // indirect
2525
github.com/pmezard/go-difflib v1.0.0 // indirect
26-
golang.org/x/net v0.10.0 // indirect
27-
golang.org/x/sys v0.8.0 // indirect
28-
golang.org/x/text v0.9.0 // indirect
29-
golang.org/x/tools v0.9.1 // indirect
26+
golang.org/x/net v0.21.0 // indirect
27+
golang.org/x/sys v0.17.0 // indirect
28+
golang.org/x/text v0.14.0 // indirect
29+
golang.org/x/tools v0.18.0 // indirect
30+
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
3031
gopkg.in/yaml.v3 v3.0.1 // indirect
3132
)

go.sum

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbV
1414
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
1515
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls=
1616
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
17-
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
18-
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
17+
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
18+
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
1919
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 h1:yAJXTCF9TqKcTiHJAE8dj7HMvPfh66eeA2JYW7eFpSE=
2020
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
2121
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
@@ -25,8 +25,11 @@ github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB7
2525
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
2626
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
2727
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
28+
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
2829
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
2930
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
31+
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
32+
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
3033
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
3134
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
3235
github.com/onsi/ginkgo/v2 v2.9.7 h1:06xGQy5www2oN160RtEZoTvnP2sPhEfePYmCDc2szss=
@@ -51,13 +54,12 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk
5154
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
5255
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
5356
golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
54-
golang.org/x/mod v0.10.0 h1:lFO9qtOdlre5W1jxS3r/4szv2/6iXxScdzjoBMXNhYk=
5557
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
5658
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
5759
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
5860
golang.org/x/net v0.3.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE=
59-
golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M=
60-
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
61+
golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4=
62+
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
6163
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
6264
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
6365
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -68,27 +70,28 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc
6870
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
6971
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
7072
golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
71-
golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU=
72-
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
73+
golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y=
74+
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
7375
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
7476
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
7577
golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA=
7678
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
7779
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
7880
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
7981
golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
80-
golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE=
81-
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
82+
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
83+
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
8284
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
8385
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
8486
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
8587
golang.org/x/tools v0.4.0/go.mod h1:UE5sM2OK9E/d67R0ANs2xJizIymRP5gJU295PvKXxjQ=
86-
golang.org/x/tools v0.9.1 h1:8WMNJAz3zrtPmnYC7ISf5dEn3MT0gY7jBJfw27yrrLo=
87-
golang.org/x/tools v0.9.1/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc=
88+
golang.org/x/tools v0.18.0 h1:k8NLag8AGHnn+PHbl7g43CtqZAwG60vZkLqgyZgIHgQ=
89+
golang.org/x/tools v0.18.0/go.mod h1:GL7B4CwcLLeo59yx/9UWWuNOW1n3VZ4f5axWfML7Lcg=
8890
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
8991
google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw=
90-
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
9192
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
93+
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
94+
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
9295
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
9396
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
9497
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

0 commit comments

Comments
 (0)