-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathhttpclient.go
168 lines (142 loc) · 3.79 KB
/
httpclient.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
160
161
162
163
164
165
166
167
168
package httpclient
import (
"crypto/tls"
"crypto/x509"
"fmt"
"io/ioutil"
"net"
"net/http"
"net/url"
"time"
)
type Option func(*http.Client) error
// New returns a HTTPClient with some sensible defaults
func New(opts ...Option) (*http.Client, error) {
dialer := net.Dialer{
Timeout: 30 * time.Second,
}
tlsConf := &tls.Config{
InsecureSkipVerify: false,
}
transport := &http.Transport{
Dial: dialer.Dial,
TLSClientConfig: tlsConf,
TLSHandshakeTimeout: 5 * time.Second,
IdleConnTimeout: 30 * time.Second,
ResponseHeaderTimeout: 120 * time.Second,
}
client := &http.Client{
Transport: transport,
}
for _, opt := range opts {
err := opt(client)
if err != nil {
return nil, err
}
}
return client, nil
}
// Insecure set the InsecureSkipVerify Option to true in the client
// this diabled verification of any server certificates
// This is an Option and should be passed to the New() function
func Insecure() Option {
return func(c *http.Client) error {
return SetInsecure(c)
}
}
// SetInsecure set the InsecureSkipVerify Option to true in the client
// this diabled verification of any server certificates
func SetInsecure(c *http.Client) error {
t, err := transport(c)
if err != nil {
return err
}
t.TLSClientConfig.InsecureSkipVerify = true
c.Transport = t
return nil
}
// ClientCert adds an client key and certificate to the client
// This is an Option and should be passed to the New() function
func ClientCert(clientCert, clientKey string) Option {
return func(c *http.Client) error {
return WithClientCert(c, clientCert, clientKey)
}
}
// ClientCert adds an client key and certificate to the client
func WithClientCert(c *http.Client, clientCert, clientKey string) error {
cert, err := tls.LoadX509KeyPair(clientCert, clientKey)
if err != nil {
return fmt.Errorf("could not load client certificate or key: %v", err)
}
t, err := transport(c)
if err != nil {
return err
}
var certs []tls.Certificate
if t.TLSClientConfig.Certificates == nil {
certs = []tls.Certificate{}
}
certs = append(certs, cert)
t.TLSClientConfig.Certificates = certs
c.Transport = t
return nil
}
// RootCA Adds a root certificate to the client
// This certificate is used to verify certificates provided by the server
// This is an Option and should be passed to the New() function
func RootCA(CACertFile string) Option {
return func(c *http.Client) error {
return WithRootCA(c, CACertFile)
}
}
// RootCA Adds a root certificate to the client
// This certificate is used to verify certificates provided by the server
func WithRootCA(c *http.Client, CACertFile string) error {
caBytes, err := ioutil.ReadFile(CACertFile)
if err != nil {
return fmt.Errorf("could not read CA certificate file: %v", err)
}
t, err := transport(c)
if err != nil {
return err
}
p := x509.NewCertPool()
if t.TLSClientConfig.RootCAs != nil {
p = t.TLSClientConfig.RootCAs
}
ok := p.AppendCertsFromPEM(caBytes)
if !ok {
return fmt.Errorf("could not add ca cert %s to certpool", CACertFile)
}
t.TLSClientConfig.RootCAs = p
c.Transport = t
return nil
}
// Proxy sets a proxy for the client
// This is an Option and should be passed to the New() function
func Proxy(proxyURL string) Option {
return func(c *http.Client) error {
return WithProxy(c, proxyURL)
}
}
// Proxy sets a proxy for the client
func WithProxy(c *http.Client, proxyURL string) error {
u, err := url.Parse(proxyURL)
if err != nil {
return fmt.Errorf("could not parse proxy url: %v", err)
}
t, err := transport(c)
if err != nil {
return err
}
t.Proxy = http.ProxyURL(u)
c.Transport = t
return nil
}
func transport(c *http.Client) (*http.Transport, error) {
t, ok := c.Transport.(*http.Transport)
if !ok {
return nil, fmt.Errorf("could not get transport from client")
}
return t, nil
}