-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathclient.go
More file actions
135 lines (106 loc) · 2.85 KB
/
client.go
File metadata and controls
135 lines (106 loc) · 2.85 KB
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
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
package autonomisdk
import (
"errors"
"fmt"
"io"
"net/http"
"net/url"
"time"
"github.com/gin-gonic/gin/binding"
"github.com/go-playground/validator/v10"
"github.com/google/uuid"
)
type pollElement struct {
retryInterval time.Duration
maxRetry int
}
type Client struct {
hostURL *url.URL
httpClient *http.Client
personalAccessToken string
accountID uuid.UUID
validate *validator.Validate
poll pollElement
}
type OptionClient func(*Client)
const timeout = 30 * time.Second
var (
ErrTermsAndConditionsRequired = errors.New("terms and conditions must be accepted")
ErrHostURLRequired = errors.New("host url must be set, please use the option WithHostURL()")
ErrPersonalAccessTokenRequired = errors.New("personal acess token must be set, please use the option WithPersonalAccessToken()")
)
func WithHostURL(url *url.URL) OptionClient {
return func(a *Client) {
a.hostURL = url
}
}
// WithHTTPClient init http client. If its timeout is above 30s it will be overide to be equal to 30 seconds
func WithHTTPClient(client *http.Client) OptionClient {
return func(a *Client) {
a.httpClient = client
if a.httpClient.Timeout > timeout {
a.httpClient.Timeout = timeout
}
}
}
func WithPersonalAccessToken(token string) OptionClient {
return func(a *Client) {
a.personalAccessToken = token
}
}
func initClient(opts ...OptionClient) *Client {
client := &Client{
httpClient: &http.Client{},
hostURL: &url.URL{},
poll: pollElement{
retryInterval: 20 * time.Second,
maxRetry: 30,
},
}
for _, o := range opts {
o(client)
}
return client
}
// NewClient - Init and return an http client
func NewClient(termsAndConditions bool, opts ...OptionClient) (*Client, error) {
if !termsAndConditions {
return nil, ErrTermsAndConditionsRequired
}
client := initClient(opts...)
if client.hostURL != nil && client.hostURL.Host == "" {
return nil, ErrHostURLRequired
}
if client.personalAccessToken == "" {
return nil, ErrPersonalAccessTokenRequired
}
accountID, err := client.GetSelf()
if err != nil {
return nil, err
}
client.accountID = accountID
validate, ok := binding.Validator.Engine().(*validator.Validate)
if !ok {
return nil, errors.New("not a valid binding validator")
}
client.validate = validate
return client, nil
}
func (c *Client) doRequest(req *http.Request) ([]byte, error) {
req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", c.personalAccessToken))
req.Header.Add("Content-Type", "application/json")
req.Header.Add("Accept", "application/json")
res, err := c.httpClient.Do(req)
if err != nil {
return nil, err
}
defer res.Body.Close()
body, err := io.ReadAll(res.Body)
if err != nil {
return nil, err
}
if res.StatusCode >= http.StatusBadRequest {
return nil, fmt.Errorf("status: %d, body: %s", res.StatusCode, body)
}
return body, err
}