Skip to content

Commit e108910

Browse files
authored
Merge pull request #5 from randlabs/new_version
Changes for V2
2 parents 0d77771 + 1b1114f commit e108910

File tree

12 files changed

+246
-209
lines changed

12 files changed

+246
-209
lines changed

.gitignore

Lines changed: 1 addition & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,5 @@
1-
21
*.~*
3-
4-
*.log
5-
*.swp
2+
qodana.yaml
63
.idea
7-
*.patch
8-
### Go template
9-
# Binaries for programs and plugins
10-
*.exe
11-
*.exe~
12-
*.dll
13-
*.so
14-
*.dylib
15-
16-
# Test binary, build with `go test -c`
17-
*.test
18-
19-
# Output of the go coverage tool, specifically when used with LiteIDE
20-
*.out
214
.DS_Store
22-
app
23-
demo
24-
255
vendor/*

LICENSE renamed to LICENSE.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@
187187
same "printed page" as the copyright notice for easier
188188
identification within third-party archives.
189189

190-
Copyright (C) 2021 RandLabs
190+
Copyright (C) 2021-2023 RandLabs
191191

192192
Licensed under the Apache License, Version 2.0 (the "License");
193193
you may not use this file except in compliance with the License.

README.md

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ The base code of this library, the balancer, *DOES NOT DO* any kind of network a
1010
import (
1111
"time"
1212

13-
balancer "github.com/randlabs/go-loadbalancer"
13+
balancer "github.com/randlabs/go-loadbalancer/v2"
1414
)
1515

1616
type ServerInfo struct {
@@ -100,7 +100,7 @@ requests among them.
100100
import (
101101
"fmt"
102102

103-
balancer "github.com/randlabs/go-loadbalancer"
103+
balancer "github.com/randlabs/go-loadbalancer/v2"
104104
)
105105

106106
func main() {
@@ -120,20 +120,22 @@ func main() {
120120
},
121121
})
122122

123-
req := hc.NewRequest("GET", "/api-test")
124-
err := req.Exec(context.Background(), func (ctx context.Context, res httpclient.Response) error {
125-
if res.Err() != nil || res.StatusCode != 200 {
126-
// Retry on the next available server on failed request
127-
res.RetryOnNextServer()
128-
return nil
129-
}
123+
err := hc.NewRequest(context.Background(), "/api-test").
124+
Method("GET").
125+
Callback(func (ctx context.Context, res httpclient.Response) error {
126+
if res.Err() != nil || res.StatusCode != 200 {
127+
// Retry on the next available server on failed request
128+
res.RetryOnNextServer()
129+
return nil
130+
}
130131

131-
// Process response
132-
// ...
132+
// Process response
133+
// ...
133134

134-
// Done
135-
return nil
136-
})
135+
// Done
136+
return nil
137+
}).
138+
Exec()
137139
}
138140
```
139141

go.mod

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
1-
module github.com/randlabs/go-loadbalancer
1+
module github.com/randlabs/go-loadbalancer/v2
22

3-
go 1.16
3+
go 1.18
44

55
require github.com/stretchr/testify v1.8.4
6+
7+
require (
8+
github.com/davecgh/go-spew v1.1.1 // indirect
9+
github.com/pmezard/go-difflib v1.0.0 // indirect
10+
gopkg.in/yaml.v3 v3.0.1 // indirect
11+
)

go.sum

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,10 @@
1-
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
21
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
32
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
43
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
54
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
6-
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
7-
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
8-
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
9-
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
10-
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
115
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
126
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
137
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
148
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
15-
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
169
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
1710
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

httpclient/exec.go

Lines changed: 24 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -8,36 +8,33 @@ import (
88
"net"
99
"net/http"
1010
"strings"
11-
"time"
1211
)
1312

1413
// -----------------------------------------------------------------------------
1514

1615
const (
17-
defaultTimeout = 20 * time.Second
18-
1916
errUnableToExecuteRequest = "failed to execute http request"
2017
errNoAvailableServer = "no available upstream server"
2118
)
2219

2320
// -----------------------------------------------------------------------------
2421

25-
func (c *HttpClient) exec(parentCtx context.Context, cb ExecCallback, req *Request) error {
26-
var httpreq *http.Request
22+
func (c *HttpClient) exec(req *Request) error {
23+
var httpReq *http.Request
2724
var getBody func() io.ReadCloser
2825
var err error
2926

3027
// Define a body getter to return multiple copies of the reader to be used in retries.
31-
if req.Body == nil {
28+
if req.body == nil {
3229
// If no body, getter will return nil
3330
getBody = func() io.ReadCloser {
3431
return nil
3532
}
3633
} else {
3734
// Convert to a ReadCloser if just a reader
38-
rc, ok := req.Body.(io.ReadCloser)
35+
rc, ok := req.body.(io.ReadCloser)
3936
if !ok {
40-
rc = io.NopCloser(req.Body)
37+
rc = io.NopCloser(req.body)
4138
}
4239

4340
// Defer close of the original body
@@ -46,7 +43,7 @@ func (c *HttpClient) exec(parentCtx context.Context, cb ExecCallback, req *Reque
4643
}()
4744

4845
// Set up a body reader cloning function
49-
switch v := req.Body.(type) {
46+
switch v := req.body.(type) {
5047
case *bytes.Buffer:
5148
buf := v.Bytes()
5249
getBody = func() io.ReadCloser {
@@ -79,37 +76,38 @@ func (c *HttpClient) exec(parentCtx context.Context, cb ExecCallback, req *Reque
7976
// Loop
8077
for {
8178
var netErr net.Error
82-
var cancelCtx context.CancelFunc
8379

8480
// Get next available server
8581
srv := c.lb.Next()
8682
if srv == nil {
87-
return c.newError(nil, errNoAvailableServer, req.Resource, 0)
83+
return c.newError(nil, errNoAvailableServer, req.url, 0)
8884
}
8985

9086
src := srv.UserData().(*Source)
9187

9288
// Create the final url
93-
url := src.baseURL + req.Resource
89+
url := src.baseURL + req.url
9490

9591
// Create a new http request
96-
httpreq, err = http.NewRequest(req.Method, url, getBody())
92+
httpReq, err = http.NewRequest(req.method, url, getBody())
9793
if err != nil {
9894
err = c.newError(err, errUnableToExecuteRequest, url, 0)
9995
src.setLastError(err)
10096
return err
10197
}
10298

10399
// Add load balancer source headers
104-
httpreq.Header = src.header.Clone()
100+
httpReq.Header = src.header.Clone()
105101

106102
// Add request headers
107-
for k, v := range req.Header {
108-
vLen := len(v)
109-
if vLen > 0 {
110-
httpreq.Header.Set(k, v[0])
111-
for vIdx := 1; vIdx < vLen; vIdx++ {
112-
httpreq.Header.Add(k, v[vIdx])
103+
if req.headers != nil {
104+
for k, v := range req.headers {
105+
vLen := len(v)
106+
if vLen > 0 {
107+
httpReq.Header.Set(k, v[0])
108+
for vIdx := 1; vIdx < vLen; vIdx++ {
109+
httpReq.Header.Add(k, v[vIdx])
110+
}
113111
}
114112
}
115113
}
@@ -119,13 +117,6 @@ func (c *HttpClient) exec(parentCtx context.Context, cb ExecCallback, req *Reque
119117
Transport: c.transport,
120118
}
121119

122-
// Establish a new context with a default timeout if a deadline is not present
123-
ctx := parentCtx
124-
cancelCtx = nil
125-
if _, hasDeadline := parentCtx.Deadline(); !hasDeadline {
126-
ctx, cancelCtx = context.WithTimeout(parentCtx, defaultTimeout)
127-
}
128-
129120
// Build callback info
130121
upstreamOffline := false
131122
retry := false
@@ -137,8 +128,11 @@ func (c *HttpClient) exec(parentCtx context.Context, cb ExecCallback, req *Reque
137128
retry: &retry,
138129
}
139130

131+
// Establish a new context with the timeout
132+
ctx, cancelCtx := context.WithTimeout(req.ctx, req.timeout)
133+
140134
// Execute real request
141-
execResult.Response, err = client.Do(httpreq.WithContext(ctx))
135+
execResult.Response, err = client.Do(httpReq.WithContext(ctx))
142136
if err != nil {
143137
if errors.Is(err, context.DeadlineExceeded) {
144138
// Deadline exceeded?
@@ -163,7 +157,7 @@ func (c *HttpClient) exec(parentCtx context.Context, cb ExecCallback, req *Reque
163157
execResult.err = err
164158

165159
// Call the callback
166-
err = cb(parentCtx, execResult)
160+
err = req.callback(ctx, execResult)
167161
if err != nil {
168162
if errors.Is(err, context.DeadlineExceeded) {
169163
err = ErrTimeout
@@ -175,9 +169,7 @@ func (c *HttpClient) exec(parentCtx context.Context, cb ExecCallback, req *Reque
175169
}
176170

177171
// To avoid defer calling inside a for loop and warnings, we call it here
178-
if cancelCtx != nil {
179-
cancelCtx()
180-
}
172+
cancelCtx()
181173

182174
// Close the response body if one exist
183175
if execResult.Response != nil {

httpclient/httpclient.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import (
77
"strings"
88
"time"
99

10-
"github.com/randlabs/go-loadbalancer"
10+
"github.com/randlabs/go-loadbalancer/v2"
1111
)
1212

1313
// -----------------------------------------------------------------------------

0 commit comments

Comments
 (0)