-
Notifications
You must be signed in to change notification settings - Fork 25
/
client.go
128 lines (108 loc) · 2.72 KB
/
client.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
package storage_go
import (
"bytes"
"encoding/json"
"io"
"net/http"
"net/url"
)
var version = "v0.7.0"
type Client struct {
clientError error
session http.Client
clientTransport transport
}
type transport struct {
header http.Header
baseUrl url.URL
}
func (t transport) RoundTrip(request *http.Request) (*http.Response, error) {
for headerName, values := range t.header {
for _, val := range values {
request.Header.Add(headerName, val)
}
}
request.URL = t.baseUrl.ResolveReference(request.URL)
return http.DefaultTransport.RoundTrip(request)
}
func NewClient(rawUrl string, token string, headers map[string]string) *Client {
baseURL, err := url.Parse(rawUrl)
if err != nil {
return &Client{
clientError: err,
}
}
t := transport{
header: http.Header{},
baseUrl: *baseURL,
}
c := Client{
session: http.Client{Transport: t},
clientTransport: t,
}
// Set required headers
c.clientTransport.header.Set("Accept", "application/json")
c.clientTransport.header.Set("Content-Type", "application/json")
c.clientTransport.header.Set("X-Client-Info", "storage-go/"+version)
c.clientTransport.header.Set("Authorization", "Bearer "+token)
// Optional headers [if exists]
for key, value := range headers {
c.clientTransport.header.Set(key, value)
}
return &c
}
// NewRequest will create new request with method, url and body
// If body is not nil, it will be marshalled into json
func (c *Client) NewRequest(method, url string, body ...interface{}) (*http.Request, error) {
var buf io.ReadWriter
if len(body) > 0 && body[0] != nil {
buf = &bytes.Buffer{}
enc := json.NewEncoder(buf)
enc.SetEscapeHTML(false)
err := enc.Encode(body[0])
if err != nil {
return nil, err
}
}
req, err := http.NewRequest(method, url, buf)
if err != nil {
return nil, err
}
return req, nil
}
// Do will send request using the c.sessionon which it is called
// If response contains body, it will be unmarshalled into v
// If response has err, it will be returned
func (c *Client) Do(req *http.Request, v interface{}) (*http.Response, error) {
resp, err := c.session.Do(req)
if err != nil {
return nil, err
}
err = checkForError(resp)
if err != nil {
return resp, err
}
if resp.Body != nil && v != nil {
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
return resp, err
}
err = json.Unmarshal(body, &v)
if err != nil {
return resp, err
}
}
return resp, nil
}
func checkForError(resp *http.Response) error {
if c := resp.StatusCode; 200 <= c && c < 400 {
return nil
}
errorResponse := &StorageError{}
data, err := io.ReadAll(resp.Body)
if err == nil && data != nil {
_ = json.Unmarshal(data, errorResponse)
}
return errorResponse
}