This repository has been archived by the owner on Nov 6, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 26
/
Copy pathclient.go
149 lines (133 loc) · 3.24 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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
package main
import (
"crypto/tls"
"errors"
"fmt"
"io"
"net/http"
"net/url"
"os"
"strings"
)
type Action interface {
// Apply runs the command with args and gets the json result.
Apply(args []string)
}
type Login struct {
Hosts []string
User string
Pass string
}
func (l *Login) NeedsAuth() bool {
// Auth is only needed if User and Pass were set
return l.User != "" && l.Pass != ""
}
func NewLogin(hosts, login string) *Login {
hostlist := strings.Split(hosts, ",")
var user, pass string
if login != "" {
toks := strings.SplitN(login, ":", 2)
user = toks[0]
pass = toks[1]
}
return &Login{
Hosts: hostlist,
User: user,
Pass: pass,
}
}
type Tool struct {
selections map[string]Selector
}
func (t *Tool) Start(args []string) {
if len(args) == 0 {
Usage()
}
if selection, ok := t.selections[args[0]]; !ok {
Usage()
} else {
selection.Select(args[1:])
}
}
type Client struct {
client http.Client
login *Login
}
func NewClient(login *Login, insecure bool) *Client {
c := http.Client{}
if tr := getTransportConfig(insecure); tr != nil {
c.Transport = tr
}
return &Client{
client: c,
login: login,
}
}
func getTransportConfig(insecure bool) *http.Transport {
cfg := &tls.Config{}
cfg.InsecureSkipVerify = insecure
return &http.Transport{
Proxy: http.ProxyFromEnvironment,
TLSClientConfig: cfg,
DisableCompression: true,
}
}
func (c *Client) Do(r *http.Request) (*http.Response, error) {
// this is not ghetto at all
original := r.URL.String()
// try each host until success or run out
for _, host := range c.login.Hosts {
fixed := strings.Replace(original, "HOST", host, 1)
url, e := url.Parse(fixed)
Check(e == nil, "could not parse fixed url", e)
r.URL = url
if response, e := c.client.Do(r); e == nil {
return response, nil
} else {
fmt.Fprintf(os.Stderr, "request to %s failed\n", host)
ourl, e := url.Parse(original)
Check(e == nil, "could not parse original url")
r.URL = ourl
}
}
return nil, errors.New("requests to all hosts failed")
}
func (c *Client) GET(path string) *http.Request {
url := "HOST" + path
request, e := http.NewRequest("GET", url, nil)
Check(e == nil, "failed to crete GET request", e)
c.tweak(request)
return request
}
func (c *Client) POST(path string, body io.Reader) *http.Request {
url := "HOST" + path
request, e := http.NewRequest("POST", url, body)
Check(e == nil, "failed to create POST request", e)
c.tweak(request)
return request
}
func (c *Client) DELETE(path string) *http.Request {
url := "HOST" + path
request, e := http.NewRequest("DELETE", url, nil)
Check(e == nil, "failed to create DELETE request", e)
c.tweak(request)
return request
}
func (c *Client) PUT(path string, body io.ReadCloser) *http.Request {
url := "HOST" + path
request, e := http.NewRequest("PUT", url, body)
Check(e == nil, "failed to create PUT request", e)
c.tweak(request)
return request
}
// tweak will set:
// Content-Type: application/json
// Accept: application/json
// Accept-Encoding: gzip, deflate, compress
func (c *Client) tweak(request *http.Request) {
request.Header.Set("Content-Type", "application/json")
request.Header.Set("Accept", "application/json")
if c.login.NeedsAuth() {
request.SetBasicAuth(c.login.User, c.login.Pass)
}
}