Add http proxy support for exec/port-forward

Add http proxy support for exec/port-forward in SpdyRoundTripper
This commit is contained in:
Andy Goldstein 2015-07-21 16:45:39 -04:00 committed by Steve Milner
parent 26c51881ca
commit e73652411e

View File

@ -23,6 +23,8 @@ import (
"io/ioutil"
"net"
"net/http"
"net/http/httputil"
"net/url"
"strings"
"k8s.io/kubernetes/pkg/api"
@ -53,21 +55,82 @@ type SpdyRoundTripper struct {
Dialer *net.Dialer
}
// NewSpdyRoundTripper creates a new SpdyRoundTripper that will use
// NewRoundTripper creates a new SpdyRoundTripper that will use
// the specified tlsConfig.
func NewRoundTripper(tlsConfig *tls.Config) httpstream.UpgradeRoundTripper {
return NewSpdyRoundTripper(tlsConfig)
}
// NewSpdyRoundTripper creates a new SpdyRoundTripper that will use
// the specified tlsConfig. This function is mostly meant for unit tests.
func NewSpdyRoundTripper(tlsConfig *tls.Config) *SpdyRoundTripper {
return &SpdyRoundTripper{tlsConfig: tlsConfig}
}
// dial dials the host specified by req, using TLS if appropriate.
// 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) {
dialAddr := netutil.CanonicalAddr(req.URL)
proxyURL, err := http.ProxyFromEnvironment(req)
if err != nil {
return nil, err
}
if req.URL.Scheme == "http" {
if proxyURL == nil {
return s.dialWithoutProxy(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: req.URL.Host,
}
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(req.URL.Host)
if err != nil {
return nil, err
}
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
}
if err := tlsConn.VerifyHostname(host); err != nil {
return nil, err
}
return tlsConn, nil
}
// 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 {