restic/internal/backend/http_transport.go

66 lines
1.8 KiB
Go
Raw Normal View History

2017-05-01 17:30:52 +00:00
package backend
import (
"crypto/tls"
"crypto/x509"
"fmt"
"io/ioutil"
2017-05-01 17:30:52 +00:00
"net"
"net/http"
"time"
2017-07-23 12:21:03 +00:00
"github.com/restic/restic/internal/debug"
2017-05-01 17:30:52 +00:00
)
// Transport returns a new http.RoundTripper with default settings applied. If
// a custom rootCertFilename is non-empty, it must point to a valid PEM file,
// otherwise the function will return an error.
func Transport(rootCertFilenames []string, tlsClientCert string, tlsClientKey string) (http.RoundTripper, error) {
2017-05-01 17:30:52 +00:00
// copied from net/http
tr := &http.Transport{
Proxy: http.ProxyFromEnvironment,
DialContext: (&net.Dialer{
Timeout: 30 * time.Second,
KeepAlive: 30 * time.Second,
DualStack: true,
}).DialContext,
MaxIdleConns: 100,
MaxIdleConnsPerHost: 100,
2017-05-01 17:30:52 +00:00
IdleConnTimeout: 90 * time.Second,
TLSHandshakeTimeout: 10 * time.Second,
ExpectContinueTimeout: 1 * time.Second,
TLSClientConfig: &tls.Config{},
}
if tlsClientCert != "" && tlsClientKey != "" {
c, err := tls.LoadX509KeyPair(tlsClientCert, tlsClientKey)
if err != nil {
return nil, fmt.Errorf("unable to read client certificate/key pair: %v", err)
}
tr.TLSClientConfig.Certificates = []tls.Certificate{c}
2017-05-01 17:30:52 +00:00
}
if rootCertFilenames == nil {
return debug.RoundTripper(tr), nil
}
p := x509.NewCertPool()
for _, filename := range rootCertFilenames {
if filename == "" {
return nil, fmt.Errorf("empty filename for root certificate supplied")
}
b, err := ioutil.ReadFile(filename)
if err != nil {
return nil, fmt.Errorf("unable to read root certificate: %v", err)
}
if ok := p.AppendCertsFromPEM(b); !ok {
return nil, fmt.Errorf("cannot parse root certificate from %q", filename)
}
}
tr.TLSClientConfig.RootCAs = p
2017-05-01 17:30:52 +00:00
// wrap in the debug round tripper
return debug.RoundTripper(tr), nil
2017-05-01 17:30:52 +00:00
}