Newer
Older
package httpclient
import (
"crypto/tls"
"crypto/x509"
"fmt"
"net"
"net/http"
"os"
"time"
)
func extractCAs(input []string) [][]byte {
result := make([][]byte, 0, len(input))
for _, ca := range input {
if ca == "" {
continue
}
pemData, err := os.ReadFile(ca)
if err != nil {
pemData, err = base64.StdEncoding.DecodeString(ca)
if err != nil {
pemData = []byte(ca)
}
}
result = append(result, pemData)
}
return result
}
func NewHTTPClient(rootCAs []string, insecureSkipVerify bool) (*http.Client, error) {
pool, err := x509.SystemCertPool()
if err != nil {
return nil, err
}
tlsConfig := tls.Config{RootCAs: pool, InsecureSkipVerify: insecureSkipVerify}
for index, rootCABytes := range extractCAs(rootCAs) {
if !tlsConfig.RootCAs.AppendCertsFromPEM(rootCABytes) {
return nil, fmt.Errorf("rootCAs.%d is not in PEM format, certificate must be "+
"a PEM encoded string, a base64 encoded bytes that contain PEM encoded string, "+
"or a path to a PEM encoded certificate", index)
}
}
return &http.Client{
Transport: &http.Transport{
TLSClientConfig: &tlsConfig,
Proxy: http.ProxyFromEnvironment,
DialContext: (&net.Dialer{
Timeout: 30 * time.Second,
KeepAlive: 30 * time.Second,
DualStack: true,
}).DialContext,
MaxIdleConns: 100,
IdleConnTimeout: 90 * time.Second,
TLSHandshakeTimeout: 10 * time.Second,
ExpectContinueTimeout: 1 * time.Second,
},
}, nil
}