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
|
package client
import (
"context"
"crypto/tls"
"crypto/x509"
"io/ioutil"
"net"
"net/http"
"path/filepath"
"strings"
"time"
)
const (
socketBaseUrl = "http://unix"
unixSocketProtocol = "http+unix://"
httpProtocol = "http://"
httpsProtocol = "https://"
defaultReadTimeoutSeconds = 300
)
type HttpClient struct {
*http.Client
Host string
}
func NewHTTPClient(gitlabURL, caFile, caPath string, selfSignedCert bool, readTimeoutSeconds uint64) *HttpClient {
var transport *http.Transport
var host string
if strings.HasPrefix(gitlabURL, unixSocketProtocol) {
transport, host = buildSocketTransport(gitlabURL)
} else if strings.HasPrefix(gitlabURL, httpProtocol) {
transport, host = buildHttpTransport(gitlabURL)
} else if strings.HasPrefix(gitlabURL, httpsProtocol) {
transport, host = buildHttpsTransport(caFile, caPath, selfSignedCert, gitlabURL)
} else {
return nil
}
c := &http.Client{
Transport: transport,
Timeout: readTimeout(readTimeoutSeconds),
}
client := &HttpClient{Client: c, Host: host}
return client
}
func buildSocketTransport(gitlabURL string) (*http.Transport, string) {
socketPath := strings.TrimPrefix(gitlabURL, unixSocketProtocol)
transport := &http.Transport{
DialContext: func(ctx context.Context, _, _ string) (net.Conn, error) {
dialer := net.Dialer{}
return dialer.DialContext(ctx, "unix", socketPath)
},
}
return transport, socketBaseUrl
}
func buildHttpsTransport(caFile, caPath string, selfSignedCert bool, gitlabURL string) (*http.Transport, string) {
certPool, err := x509.SystemCertPool()
if err != nil {
certPool = x509.NewCertPool()
}
if caFile != "" {
addCertToPool(certPool, caFile)
}
if caPath != "" {
fis, _ := ioutil.ReadDir(caPath)
for _, fi := range fis {
if fi.IsDir() {
continue
}
addCertToPool(certPool, filepath.Join(caPath, fi.Name()))
}
}
transport := &http.Transport{
TLSClientConfig: &tls.Config{
RootCAs: certPool,
InsecureSkipVerify: selfSignedCert,
},
}
return transport, gitlabURL
}
func addCertToPool(certPool *x509.CertPool, fileName string) {
cert, err := ioutil.ReadFile(fileName)
if err == nil {
certPool.AppendCertsFromPEM(cert)
}
}
func buildHttpTransport(gitlabURL string) (*http.Transport, string) {
return &http.Transport{}, gitlabURL
}
func readTimeout(timeoutSeconds uint64) time.Duration {
if timeoutSeconds == 0 {
timeoutSeconds = defaultReadTimeoutSeconds
}
return time.Duration(timeoutSeconds) * time.Second
}
|