-
Notifications
You must be signed in to change notification settings - Fork 4.8k
/
client.go
117 lines (97 loc) · 2.57 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
package chartserver
import (
"errors"
"fmt"
"io"
"io/ioutil"
"net/http"
"net/url"
"strings"
"time"
)
const (
clientTimeout = 10 * time.Second
maxIdleConnections = 10
idleConnectionTimeout = 30 * time.Second
)
// ChartClient is a http client to get the content from the external http server
type ChartClient struct {
// HTTP client
httpClient *http.Client
// Auth info
credentail *Credential
}
// NewChartClient is constructor of ChartClient
// credentail can be nil
func NewChartClient(credentail *Credential) *ChartClient { // Create http client with customized timeouts
client := &http.Client{
Timeout: clientTimeout,
Transport: &http.Transport{
MaxIdleConns: maxIdleConnections,
IdleConnTimeout: idleConnectionTimeout,
},
}
return &ChartClient{
httpClient: client,
credentail: credentail,
}
}
// GetContent get the bytes from the specified url
func (cc *ChartClient) GetContent(addr string) ([]byte, error) {
response, err := cc.sendRequest(addr, http.MethodGet, nil, []int{http.StatusOK})
if err != nil {
return nil, err
}
content, err := ioutil.ReadAll(response.Body)
if err != nil {
return nil, err
}
defer response.Body.Close()
return content, nil
}
// DeleteContent sends deleting request to the addr to delete content
func (cc *ChartClient) DeleteContent(addr string) error {
_, err := cc.sendRequest(addr, http.MethodDelete, nil, []int{http.StatusOK})
return err
}
// sendRequest sends requests to the addr with the specified spec
func (cc *ChartClient) sendRequest(addr string, method string, body io.Reader, expectedCodes []int) (*http.Response, error) {
if len(strings.TrimSpace(addr)) == 0 {
return nil, errors.New("empty url is not allowed")
}
fullURI, err := url.Parse(addr)
if err != nil {
return nil, fmt.Errorf("invalid url: %s", err.Error())
}
request, err := http.NewRequest(method, addr, body)
if err != nil {
return nil, err
}
// Set basic auth
if cc.credentail != nil {
request.SetBasicAuth(cc.credentail.Username, cc.credentail.Password)
}
response, err := cc.httpClient.Do(request)
if err != nil {
return nil, err
}
isExpectedStatusCode := false
for _, eCode := range expectedCodes {
if eCode == response.StatusCode {
isExpectedStatusCode = true
break
}
}
if !isExpectedStatusCode {
content, err := ioutil.ReadAll(response.Body)
if err != nil {
return nil, err
}
defer response.Body.Close()
if err := extractError(content); err != nil {
return nil, err
}
return nil, fmt.Errorf("%s '%s' failed with error: %s", method, fullURI.Path, content)
}
return response, nil
}