This repository has been archived by the owner on Aug 12, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
workwave.go
145 lines (127 loc) · 3.17 KB
/
workwave.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
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
136
137
138
139
140
141
142
143
144
145
package workwave
import (
"bytes"
"context"
"encoding/json"
"fmt"
"io"
"net"
"net/http"
"net/url"
"runtime"
"time"
"github.com/pkg/errors"
)
const (
agentString = "tkh/go-workwave"
contentType = "application/json"
apiBaseURL = "https://wwrm.workwave.com"
)
// Client is a structure that provides access to the WorkWave API.
// https://wwrm.workwave.com/api/
type Client struct {
client *http.Client
baseURL *url.URL
apiKey string
Callback CallbackService
Orders OrdersService
Routes RoutesService
}
// New creates a new WorkWave API client with the given API key for authentication.
func New(apiKey string) (*Client, error) {
baseURL, err := url.Parse(apiBaseURL)
if err != nil {
return nil, err
}
c := &Client{
client: newHTTPClient(),
baseURL: baseURL,
apiKey: apiKey,
}
c.Callback = &callbackService{client: c}
c.Orders = &ordersService{client: c}
c.Routes = &routesService{client: c}
return c, nil
}
// newHTTPClient creates an http.Client with timeouts which will be used to make
// requests to the Clubhouse API.
func newHTTPClient() *http.Client {
return &http.Client{
Transport: &http.Transport{
Proxy: http.ProxyFromEnvironment,
DialContext: (&net.Dialer{
Timeout: 30 * time.Second,
KeepAlive: 30 * time.Second,
DualStack: true,
}).DialContext,
MaxIdleConns: 100,
IdleConnTimeout: 60 * time.Second,
TLSHandshakeTimeout: 10 * time.Second,
ExpectContinueTimeout: 2 * time.Second,
MaxIdleConnsPerHost: runtime.GOMAXPROCS(0) + 1,
},
}
}
// NewRequest prepares an API HTTP request using the given method and path.
// If body is given, it will be converted to JSON and included in the request.
func (c *Client) NewRequest(ctx context.Context, method, path string, body interface{}) (*http.Request, error) {
u, err := c.baseURL.Parse(path)
if err != nil {
return nil, err
}
buf := new(bytes.Buffer)
if body != nil {
err = json.NewEncoder(buf).Encode(body)
if err != nil {
return nil, err
}
}
req, err := http.NewRequest(method, u.String(), buf)
if err != nil {
return nil, err
}
// Add HTTP headers
req.Header.Add("X-WorkWave-Key", c.apiKey)
req.Header.Add("User-Agent", agentString)
req.Header.Add("Content-Type", contentType)
req.Header.Add("Accept", contentType)
return req, nil
}
// Do submits an HTTP request with the Client's HTTP client.
func (c *Client) Do(ctx context.Context, req *http.Request, v interface{}) (*http.Response, error) {
req = req.WithContext(ctx)
res, err := c.client.Do(req)
if err != nil {
return nil, err
}
defer func() {
if rerr := res.Body.Close(); err == nil {
err = rerr
}
}()
err = checkResponse(res)
if err != nil {
return res, err
}
if v != nil {
if w, ok := v.(io.Writer); ok {
_, err = io.Copy(w, res.Body)
if err != nil {
return nil, errors.Wrap(err, "failed to copy response body to writer")
}
} else {
err = json.NewDecoder(res.Body).Decode(v)
if err != nil {
return nil, errors.Wrap(err, "failed to decode JSON")
}
}
}
return res, err
}
func checkResponse(res *http.Response) error {
sc := res.StatusCode
if sc >= 200 && sc <= 200 {
return nil
}
return fmt.Errorf("HTTP %d error", sc)
}