-
Notifications
You must be signed in to change notification settings - Fork 26
/
client.go
159 lines (144 loc) · 4.38 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
150
151
152
153
154
155
156
157
158
159
// Package infoblox implements an Infoblox DNS/DHCP appliance client library in Go
package infoblox
import (
"crypto/tls"
"fmt"
"log"
"net/http"
"net/http/cookiejar"
"net/url"
"strings"
"golang.org/x/net/publicsuffix"
)
var (
// WapiVersion specifies the version of the Infoblox REST API to target
WapiVersion = "1.4.1"
// BasePath specifies the default path prefix to all WAPI actions
BasePath = "/wapi/v" + WapiVersion + "/"
// Debug mode flag
Debug = false
)
// Client implements a Infoblox WAPI client.
// https://192.168.2.200/wapidoc/#transport-and-authentication
type Client struct {
Host string
Password string
Username string
HTTPClient *http.Client
UseCookies bool
}
// NewClient instantiates a new Infoblox client with the supplied user/pass configuration.
// Supports the use of HTTP proxies through the $HTTP_PROXY env var.
// For example:
// export HTTP_PROXY=http://localhost:8888
//
// When using a proxy, disable TLS certificate verification with the following:
// sslVerify = false
//
// To save and re-use infoblox session cookies, set useCookies = true
// NOTE: The infoblox cookie uses a comma separated string, and requires golang 1.3+ to be correctly stored.
func NewClient(host, username, password string, sslVerify, useCookies bool) *Client {
var (
req, _ = http.NewRequest("GET", host, nil)
proxy, _ = http.ProxyFromEnvironment(req)
transport *http.Transport
tlsconfig *tls.Config
)
tlsconfig = &tls.Config{
InsecureSkipVerify: !sslVerify,
}
if tlsconfig.InsecureSkipVerify {
log.Printf("WARNING: SSL cert verification disabled\n")
}
transport = &http.Transport{
TLSClientConfig: tlsconfig,
}
if proxy != nil {
transport.Proxy = http.ProxyURL(proxy)
}
client := &Client{
Host: host,
HTTPClient: &http.Client{
Transport: transport,
},
Username: username,
Password: password,
UseCookies: useCookies,
}
if useCookies {
options := cookiejar.Options{
PublicSuffixList: publicsuffix.List,
}
jar, _ := cookiejar.New(&options)
client.HTTPClient.Jar = jar
}
return client
}
// NewClientWithVersion instantiates a new Infoblox client from the provided parameters and sets
// the WAPI version to a user defined one.
func NewClientWithVersion(host, username, password, wapiVersion string, sslVerify, useCookies bool) *Client {
// If the WAPI version parameter is provided from the client user, set the
// global WapiVersion variable to it.
if wapiVersion != "" {
WapiVersion = wapiVersion
BasePath = "/wapi/v" + WapiVersion + "/"
}
return NewClient(host, username, password, sslVerify, useCookies)
}
// SendRequest sends a HTTP request through this instance's HTTP client.
// Uses cookies if specified, re-creating the request and falling back to basic auth if a cookie is not present
func (c *Client) SendRequest(method, urlStr, body string, head map[string]string) (resp *APIResponse, err error) {
// log.Printf("%s %s payload: %s\n", method, urlStr, body)
req, err := c.buildRequest(method, urlStr, body, head)
if err != nil {
return nil, fmt.Errorf("error creating request: %v", err)
}
var r *http.Response
if !c.UseCookies {
// Go right to basic auth if we arent using cookies
req.SetBasicAuth(c.Username, c.Password)
}
r, err = c.HTTPClient.Do(req)
if err != nil {
return nil, fmt.Errorf("error executing request: %v", err)
}
if r.StatusCode == 401 && c.UseCookies { // don't bother re-sending if we aren't using cookies
log.Printf("Re-sending request with basic auth after 401")
// Re-build request
req, err = c.buildRequest(method, urlStr, body, head)
if err != nil {
return nil, fmt.Errorf("error re-creating request: %v", err)
}
// Set basic auth
req.SetBasicAuth(c.Username, c.Password)
// Resend request
r, err = c.HTTPClient.Do(req)
}
resp = (*APIResponse)(r)
return
}
// build a new http request from this client
func (c *Client) buildRequest(method, urlStr, body string, head map[string]string) (*http.Request, error) {
var req *http.Request
var err error
if body == "" {
req, err = http.NewRequest(method, urlStr, nil)
} else {
b := strings.NewReader(body)
req, err = http.NewRequest(method, urlStr, b)
}
if err != nil {
return nil, err
}
if !strings.HasPrefix(urlStr, "http") {
u := fmt.Sprintf("%v%v", c.Host, urlStr)
req.URL, err = url.Parse(u)
if err != nil {
return nil, err
}
}
for k, v := range head {
req.Header.Set(k, v)
}
return req, err
}