func TestProxyUpgrade(t *testing.T) { backendServer := httptest.NewServer(websocket.Handler(func(ws *websocket.Conn) { defer ws.Close() body := make([]byte, 5) ws.Read(body) ws.Write([]byte("hello " + string(body))) })) defer backendServer.Close() serverURL, _ := url.Parse(backendServer.URL) proxyHandler := &UpgradeAwareProxyHandler{ Location: serverURL, } proxy := httptest.NewServer(proxyHandler) defer proxy.Close() ws, err := websocket.Dial("ws://"+proxy.Listener.Addr().String()+"/some/path", "", "http://127.0.0.1/") if err != nil { t.Fatalf("websocket dial err: %s", err) } defer ws.Close() if _, err := ws.Write([]byte("world")); err != nil { t.Fatalf("write err: %s", err) } response := make([]byte, 20) n, err := ws.Read(response) if err != nil { t.Fatalf("read err: %s", err) } if e, a := "hello world", string(response[0:n]); e != a { t.Fatalf("expected '%#v', got '%#v'", e, a) } }
func TestProxyUpgradeErrorResponse(t *testing.T) { var ( responder *fakeResponder expectedErr = errors.New("EXPECTED") ) proxy := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { transport := http.DefaultTransport.(*http.Transport) transport.Dial = func(network, addr string) (net.Conn, error) { return &fakeConn{err: expectedErr}, nil } responder = &fakeResponder{t: t, w: w} proxyHandler := &UpgradeAwareProxyHandler{ Location: &url.URL{ Host: "fake-backend", }, UpgradeRequired: true, Responder: responder, Transport: transport, } proxyHandler.ServeHTTP(w, r) })) defer proxy.Close() // Send request to proxy server. req, err := http.NewRequest("POST", "http://"+proxy.Listener.Addr().String()+"/some/path", nil) require.NoError(t, err) req.Header.Set(httpstream.HeaderConnection, httpstream.HeaderUpgrade) resp, err := http.DefaultClient.Do(req) require.NoError(t, err) defer resp.Body.Close() // Expect error response. assert.True(t, responder.called) assert.Equal(t, fakeStatusCode, resp.StatusCode) msg, err := ioutil.ReadAll(resp.Body) require.NoError(t, err) assert.Contains(t, string(msg), expectedErr.Error()) }
func TestProxyUpgrade(t *testing.T) { localhostPool := x509.NewCertPool() if !localhostPool.AppendCertsFromPEM(localhostCert) { t.Errorf("error setting up localhostCert pool") } testcases := map[string]struct { ServerFunc func(http.Handler) *httptest.Server ProxyTransport http.RoundTripper }{ "http": { ServerFunc: httptest.NewServer, ProxyTransport: nil, }, "https (invalid hostname + InsecureSkipVerify)": { ServerFunc: func(h http.Handler) *httptest.Server { cert, err := tls.X509KeyPair(exampleCert, exampleKey) if err != nil { t.Errorf("https (invalid hostname): proxy_test: %v", err) } ts := httptest.NewUnstartedServer(h) ts.TLS = &tls.Config{ Certificates: []tls.Certificate{cert}, } ts.StartTLS() return ts }, ProxyTransport: utilnet.SetTransportDefaults(&http.Transport{TLSClientConfig: &tls.Config{InsecureSkipVerify: true}}), }, "https (valid hostname + RootCAs)": { ServerFunc: func(h http.Handler) *httptest.Server { cert, err := tls.X509KeyPair(localhostCert, localhostKey) if err != nil { t.Errorf("https (valid hostname): proxy_test: %v", err) } ts := httptest.NewUnstartedServer(h) ts.TLS = &tls.Config{ Certificates: []tls.Certificate{cert}, } ts.StartTLS() return ts }, ProxyTransport: utilnet.SetTransportDefaults(&http.Transport{TLSClientConfig: &tls.Config{RootCAs: localhostPool}}), }, "https (valid hostname + RootCAs + custom dialer)": { ServerFunc: func(h http.Handler) *httptest.Server { cert, err := tls.X509KeyPair(localhostCert, localhostKey) if err != nil { t.Errorf("https (valid hostname): proxy_test: %v", err) } ts := httptest.NewUnstartedServer(h) ts.TLS = &tls.Config{ Certificates: []tls.Certificate{cert}, } ts.StartTLS() return ts }, ProxyTransport: utilnet.SetTransportDefaults(&http.Transport{Dial: net.Dial, TLSClientConfig: &tls.Config{RootCAs: localhostPool}}), }, } for k, tc := range testcases { backendServer := tc.ServerFunc(websocket.Handler(func(ws *websocket.Conn) { defer ws.Close() body := make([]byte, 5) ws.Read(body) ws.Write([]byte("hello " + string(body))) })) defer backendServer.Close() serverURL, _ := url.Parse(backendServer.URL) proxyHandler := &UpgradeAwareProxyHandler{ Location: serverURL, Transport: tc.ProxyTransport, } proxy := httptest.NewServer(proxyHandler) defer proxy.Close() ws, err := websocket.Dial("ws://"+proxy.Listener.Addr().String()+"/some/path", "", "http://127.0.0.1/") if err != nil { t.Fatalf("%s: websocket dial err: %s", k, err) } defer ws.Close() if _, err := ws.Write([]byte("world")); err != nil { t.Fatalf("%s: write err: %s", k, err) } response := make([]byte, 20) n, err := ws.Read(response) if err != nil { t.Fatalf("%s: read err: %s", k, err) } if e, a := "hello world", string(response[0:n]); e != a { t.Fatalf("%s: expected '%#v', got '%#v'", k, e, a) } } }
func TestProxyUpgrade(t *testing.T) { localhostPool := x509.NewCertPool() if !localhostPool.AppendCertsFromPEM(localhostCert) { t.Errorf("error setting up localhostCert pool") } testcases := map[string]struct { ServerFunc func(http.Handler) *httptest.Server ProxyTransport http.RoundTripper }{ "http": { ServerFunc: httptest.NewServer, ProxyTransport: nil, }, "https (invalid hostname + InsecureSkipVerify)": { ServerFunc: func(h http.Handler) *httptest.Server { cert, err := tls.X509KeyPair(exampleCert, exampleKey) if err != nil { t.Errorf("https (invalid hostname): proxy_test: %v", err) } ts := httptest.NewUnstartedServer(h) ts.TLS = &tls.Config{ Certificates: []tls.Certificate{cert}, } ts.StartTLS() return ts }, ProxyTransport: utilnet.SetTransportDefaults(&http.Transport{TLSClientConfig: &tls.Config{InsecureSkipVerify: true}}), }, "https (valid hostname + RootCAs)": { ServerFunc: func(h http.Handler) *httptest.Server { cert, err := tls.X509KeyPair(localhostCert, localhostKey) if err != nil { t.Errorf("https (valid hostname): proxy_test: %v", err) } ts := httptest.NewUnstartedServer(h) ts.TLS = &tls.Config{ Certificates: []tls.Certificate{cert}, } ts.StartTLS() return ts }, ProxyTransport: utilnet.SetTransportDefaults(&http.Transport{TLSClientConfig: &tls.Config{RootCAs: localhostPool}}), }, "https (valid hostname + RootCAs + custom dialer)": { ServerFunc: func(h http.Handler) *httptest.Server { cert, err := tls.X509KeyPair(localhostCert, localhostKey) if err != nil { t.Errorf("https (valid hostname): proxy_test: %v", err) } ts := httptest.NewUnstartedServer(h) ts.TLS = &tls.Config{ Certificates: []tls.Certificate{cert}, } ts.StartTLS() return ts }, ProxyTransport: utilnet.SetTransportDefaults(&http.Transport{Dial: net.Dial, TLSClientConfig: &tls.Config{RootCAs: localhostPool}}), }, } // Enable StreamingProxyRedirects for test. utilconfig.DefaultFeatureGate.Set("StreamingProxyRedirects=true") for k, tc := range testcases { for _, redirect := range []bool{false, true} { tcName := k backendPath := "/hello" if redirect { tcName += " with redirect" backendPath = "/redirect" } func() { // Cleanup after each test case. backend := http.NewServeMux() backend.Handle("/hello", websocket.Handler(func(ws *websocket.Conn) { defer ws.Close() body := make([]byte, 5) ws.Read(body) ws.Write([]byte("hello " + string(body))) })) backend.Handle("/redirect", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { http.Redirect(w, r, "/hello", http.StatusFound) })) backendServer := tc.ServerFunc(backend) defer backendServer.Close() serverURL, _ := url.Parse(backendServer.URL) serverURL.Path = backendPath proxyHandler := &UpgradeAwareProxyHandler{ Location: serverURL, Transport: tc.ProxyTransport, InterceptRedirects: redirect, } proxy := httptest.NewServer(proxyHandler) defer proxy.Close() ws, err := websocket.Dial("ws://"+proxy.Listener.Addr().String()+"/some/path", "", "http://127.0.0.1/") if err != nil { t.Fatalf("%s: websocket dial err: %s", tcName, err) } defer ws.Close() if _, err := ws.Write([]byte("world")); err != nil { t.Fatalf("%s: write err: %s", tcName, err) } response := make([]byte, 20) n, err := ws.Read(response) if err != nil { t.Fatalf("%s: read err: %s", tcName, err) } if e, a := "hello world", string(response[0:n]); e != a { t.Fatalf("%s: expected '%#v', got '%#v'", tcName, e, a) } }() } } }