-
Notifications
You must be signed in to change notification settings - Fork 2
/
request.go
105 lines (96 loc) · 2.36 KB
/
request.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
package request
import (
"bytes"
"io/ioutil"
netHttp "net/http"
"strings"
"time"
)
// ClientOptions struct contains options for HTTP Client which will
// be long lived client
type ClientOptions struct {
Timeout int
}
// Client struct contains reference to internal http client
type Client struct {
backendClient *netHttp.Client
}
// RequestOptions struct
type RequestOptions struct {
Method string
URL string
Body string
Retries int
Query map[string]string
Headers map[string]string
RetryInterval time.Duration // retry after x milliseconds
}
// Response struct
type Response struct {
Body, Status string
StatusCode int
Header map[string][]string
Cookies []*netHttp.Cookie
Latency int64
Retries int
}
// NewClient method returns a pointer to the Client
func NewClient(opts *ClientOptions) *Client {
var c = &netHttp.Client{
Timeout: time.Duration(opts.Timeout) * time.Second,
}
var client = &Client{backendClient: c}
return client
}
// Request method will make a request
func (c *Client) Request(opts *RequestOptions) (*Response, error) {
var url = opts.URL
if !strings.Contains(opts.URL, "?") {
url += "?"
}
for k, v := range opts.Query {
url += "&" + k + "=" + v
}
byteBody := []byte(opts.Body)
var body = bytes.NewBuffer(byteBody)
var req, err = netHttp.NewRequest(opts.Method, url, body)
for k, v := range opts.Headers {
req.Header.Set(k, v)
}
if err != nil {
return nil, err
}
var lastError error
if opts.RetryInterval == 0 {
opts.RetryInterval = 1 * time.Second
}
if opts.Retries == 0 {
opts.Retries = 1
}
var respData = &Response{}
for index := 0; index < opts.Retries; index++ {
start := time.Now()
var resp, err = c.backendClient.Do(req)
if err != nil {
lastError = err
// If request is failed then retry after sleeping for some time
time.Sleep(opts.RetryInterval)
continue
}
latency := (time.Now().UnixNano() - start.UnixNano()) / 1000000
defer resp.Body.Close()
body, readErr := ioutil.ReadAll(resp.Body)
respData.Body = string(body)
respData.Status = resp.Status
respData.StatusCode = resp.StatusCode
respData.Cookies = resp.Cookies()
respData.Header = resp.Header
respData.Latency = latency
respData.Retries = index
if readErr != nil {
return respData, readErr
}
break // since it is success break out of the for loop
}
return respData, lastError
}