|
|
@@ -298,12 +298,8 @@ func (d *Dialer) Dial(urlStr string, requestHeader http.Header) (*Conn, *http.Re
|
|
|
}
|
|
|
|
|
|
if u.Scheme == "https" {
|
|
|
- cfg := d.TLSClientConfig
|
|
|
- if cfg == nil {
|
|
|
- cfg = &tls.Config{ServerName: hostNoPort}
|
|
|
- } else if cfg.ServerName == "" {
|
|
|
- shallowCopy := *cfg
|
|
|
- cfg = &shallowCopy
|
|
|
+ cfg := cloneTLSConfig(d.TLSClientConfig)
|
|
|
+ if cfg.ServerName == "" {
|
|
|
cfg.ServerName = hostNoPort
|
|
|
}
|
|
|
tlsConn := tls.Client(netConn, cfg)
|
|
|
@@ -348,3 +344,32 @@ func (d *Dialer) Dial(urlStr string, requestHeader http.Header) (*Conn, *http.Re
|
|
|
netConn = nil // to avoid close in defer.
|
|
|
return conn, resp, nil
|
|
|
}
|
|
|
+
|
|
|
+// cloneTLSConfig clones all public fields except the fields
|
|
|
+// SessionTicketsDisabled and SessionTicketKey. This avoids copying the
|
|
|
+// sync.Mutex in the sync.Once and makes it safe to call cloneTLSConfig on a
|
|
|
+// config in active use.
|
|
|
+func cloneTLSConfig(cfg *tls.Config) *tls.Config {
|
|
|
+ if cfg == nil {
|
|
|
+ return &tls.Config{}
|
|
|
+ }
|
|
|
+ return &tls.Config{
|
|
|
+ Rand: cfg.Rand,
|
|
|
+ Time: cfg.Time,
|
|
|
+ Certificates: cfg.Certificates,
|
|
|
+ NameToCertificate: cfg.NameToCertificate,
|
|
|
+ GetCertificate: cfg.GetCertificate,
|
|
|
+ RootCAs: cfg.RootCAs,
|
|
|
+ NextProtos: cfg.NextProtos,
|
|
|
+ ServerName: cfg.ServerName,
|
|
|
+ ClientAuth: cfg.ClientAuth,
|
|
|
+ ClientCAs: cfg.ClientCAs,
|
|
|
+ InsecureSkipVerify: cfg.InsecureSkipVerify,
|
|
|
+ CipherSuites: cfg.CipherSuites,
|
|
|
+ PreferServerCipherSuites: cfg.PreferServerCipherSuites,
|
|
|
+ ClientSessionCache: cfg.ClientSessionCache,
|
|
|
+ MinVersion: cfg.MinVersion,
|
|
|
+ MaxVersion: cfg.MaxVersion,
|
|
|
+ CurvePreferences: cfg.CurvePreferences,
|
|
|
+ }
|
|
|
+}
|