// dialWithoutProxy dials the host specified by url, using TLS if appropriate. func (s *SpdyRoundTripper) dialWithoutProxy(url *url.URL) (net.Conn, error) { dialAddr := netutil.CanonicalAddr(url) if url.Scheme == "http" { if s.Dialer == nil { return net.Dial("tcp", dialAddr) } else { return s.Dialer.Dial("tcp", dialAddr) } } // TODO validate the TLSClientConfig is set up? var conn *tls.Conn var err error if s.Dialer == nil { conn, err = tls.Dial("tcp", dialAddr, s.tlsConfig) } else { conn, err = tls.DialWithDialer(s.Dialer, "tcp", dialAddr, s.tlsConfig) } if err != nil { return nil, err } // Return if we were configured to skip validation if s.tlsConfig != nil && s.tlsConfig.InsecureSkipVerify { return conn, nil } host, _, err := net.SplitHostPort(dialAddr) if err != nil { return nil, err } err = conn.VerifyHostname(host) if err != nil { return nil, err } return conn, nil }
// dial dials the host specified by req, using TLS if appropriate, optionally // using a proxy server if one is configured via environment variables. func (s *SpdyRoundTripper) dial(req *http.Request) (net.Conn, error) { proxier := s.proxier if proxier == nil { proxier = http.ProxyFromEnvironment } proxyURL, err := proxier(req) if err != nil { return nil, err } if proxyURL == nil { return s.dialWithoutProxy(req.URL) } // ensure we use a canonical host with proxyReq targetHost := netutil.CanonicalAddr(req.URL) // proxying logic adapted from http://blog.h6t.eu/post/74098062923/golang-websocket-with-http-proxy-support proxyReq := http.Request{ Method: "CONNECT", URL: &url.URL{}, Host: targetHost, } if pa := s.proxyAuth(proxyURL); pa != "" { proxyReq.Header = http.Header{} proxyReq.Header.Set("Proxy-Authorization", pa) } proxyDialConn, err := s.dialWithoutProxy(proxyURL) if err != nil { return nil, err } proxyClientConn := httputil.NewProxyClientConn(proxyDialConn, nil) _, err = proxyClientConn.Do(&proxyReq) if err != nil && err != httputil.ErrPersistEOF { return nil, err } rwc, _ := proxyClientConn.Hijack() if req.URL.Scheme != "https" { return rwc, nil } host, _, err := net.SplitHostPort(targetHost) if err != nil { return nil, err } if s.tlsConfig == nil { s.tlsConfig = &tls.Config{} } if len(s.tlsConfig.ServerName) == 0 { s.tlsConfig.ServerName = host } tlsConn := tls.Client(rwc, s.tlsConfig) // need to manually call Handshake() so we can call VerifyHostname() below if err := tlsConn.Handshake(); err != nil { return nil, err } // Return if we were configured to skip validation if s.tlsConfig != nil && s.tlsConfig.InsecureSkipVerify { return tlsConn, nil } if err := tlsConn.VerifyHostname(host); err != nil { return nil, err } return tlsConn, nil }