Example #1
0
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())
}
Example #3
0
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)
				}
			}()
		}
	}
}