|
|
|
@@ -501,61 +501,54 @@ func TestProxyUpgrade(t *testing.T) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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) {
|
|
|
|
|
if ws.Request().Header.Get("Authorization") != tc.ExpectedAuth {
|
|
|
|
|
t.Errorf("%s: unexpected headers on request: %v", k, ws.Request().Header)
|
|
|
|
|
defer ws.Close()
|
|
|
|
|
ws.Write([]byte("you failed"))
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
tcName := k
|
|
|
|
|
backendPath := "/hello"
|
|
|
|
|
func() { // Cleanup after each test case.
|
|
|
|
|
backend := http.NewServeMux()
|
|
|
|
|
backend.Handle("/hello", websocket.Handler(func(ws *websocket.Conn) {
|
|
|
|
|
if ws.Request().Header.Get("Authorization") != tc.ExpectedAuth {
|
|
|
|
|
t.Errorf("%s: unexpected headers on request: %v", k, ws.Request().Header)
|
|
|
|
|
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 := NewUpgradeAwareHandler(serverURL, tc.ProxyTransport, false, false, &noErrorsAllowed{t: t})
|
|
|
|
|
proxyHandler.UpgradeTransport = tc.UpgradeTransport
|
|
|
|
|
proxyHandler.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)
|
|
|
|
|
ws.Write([]byte("you failed"))
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
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()
|
|
|
|
|
|
|
|
|
|
if _, err := ws.Write([]byte("world")); err != nil {
|
|
|
|
|
t.Fatalf("%s: write err: %s", tcName, err)
|
|
|
|
|
}
|
|
|
|
|
serverURL, _ := url.Parse(backendServer.URL)
|
|
|
|
|
serverURL.Path = backendPath
|
|
|
|
|
proxyHandler := NewUpgradeAwareHandler(serverURL, tc.ProxyTransport, false, false, &noErrorsAllowed{t: t})
|
|
|
|
|
proxyHandler.UpgradeTransport = tc.UpgradeTransport
|
|
|
|
|
proxy := httptest.NewServer(proxyHandler)
|
|
|
|
|
defer proxy.Close()
|
|
|
|
|
|
|
|
|
|
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)
|
|
|
|
|
}
|
|
|
|
|
}()
|
|
|
|
|
}
|
|
|
|
|
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)
|
|
|
|
|
}
|
|
|
|
|
}()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -614,107 +607,100 @@ func TestProxyUpgradeConnectionErrorResponse(t *testing.T) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestProxyUpgradeErrorResponseTerminates(t *testing.T) {
|
|
|
|
|
for _, intercept := range []bool{true, false} {
|
|
|
|
|
for _, code := range []int{400, 500} {
|
|
|
|
|
t.Run(fmt.Sprintf("intercept=%v,code=%v", intercept, code), func(t *testing.T) {
|
|
|
|
|
// Set up a backend server
|
|
|
|
|
backend := http.NewServeMux()
|
|
|
|
|
backend.Handle("/hello", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
|
|
|
w.WriteHeader(code)
|
|
|
|
|
w.Write([]byte(`some data`))
|
|
|
|
|
}))
|
|
|
|
|
backend.Handle("/there", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
|
|
|
t.Error("request to /there")
|
|
|
|
|
}))
|
|
|
|
|
backendServer := httptest.NewServer(backend)
|
|
|
|
|
defer backendServer.Close()
|
|
|
|
|
backendServerURL, _ := url.Parse(backendServer.URL)
|
|
|
|
|
backendServerURL.Path = "/hello"
|
|
|
|
|
for _, code := range []int{400, 500} {
|
|
|
|
|
t.Run(fmt.Sprintf("code=%v", code), func(t *testing.T) {
|
|
|
|
|
// Set up a backend server
|
|
|
|
|
backend := http.NewServeMux()
|
|
|
|
|
backend.Handle("/hello", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
|
|
|
w.WriteHeader(code)
|
|
|
|
|
w.Write([]byte(`some data`))
|
|
|
|
|
}))
|
|
|
|
|
backend.Handle("/there", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
|
|
|
t.Error("request to /there")
|
|
|
|
|
}))
|
|
|
|
|
backendServer := httptest.NewServer(backend)
|
|
|
|
|
defer backendServer.Close()
|
|
|
|
|
backendServerURL, _ := url.Parse(backendServer.URL)
|
|
|
|
|
backendServerURL.Path = "/hello"
|
|
|
|
|
|
|
|
|
|
// Set up a proxy pointing to a specific path on the backend
|
|
|
|
|
proxyHandler := NewUpgradeAwareHandler(backendServerURL, nil, false, false, &noErrorsAllowed{t: t})
|
|
|
|
|
proxyHandler.InterceptRedirects = intercept
|
|
|
|
|
proxy := httptest.NewServer(proxyHandler)
|
|
|
|
|
defer proxy.Close()
|
|
|
|
|
proxyURL, _ := url.Parse(proxy.URL)
|
|
|
|
|
// Set up a proxy pointing to a specific path on the backend
|
|
|
|
|
proxyHandler := NewUpgradeAwareHandler(backendServerURL, nil, false, false, &noErrorsAllowed{t: t})
|
|
|
|
|
proxy := httptest.NewServer(proxyHandler)
|
|
|
|
|
defer proxy.Close()
|
|
|
|
|
proxyURL, _ := url.Parse(proxy.URL)
|
|
|
|
|
|
|
|
|
|
conn, err := net.Dial("tcp", proxyURL.Host)
|
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
bufferedReader := bufio.NewReader(conn)
|
|
|
|
|
conn, err := net.Dial("tcp", proxyURL.Host)
|
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
bufferedReader := bufio.NewReader(conn)
|
|
|
|
|
|
|
|
|
|
// Send upgrade request resulting in a non-101 response from the backend
|
|
|
|
|
req, _ := http.NewRequest("GET", "/", nil)
|
|
|
|
|
req.Header.Set(httpstream.HeaderConnection, httpstream.HeaderUpgrade)
|
|
|
|
|
require.NoError(t, req.Write(conn))
|
|
|
|
|
// Verify we get the correct response and full message body content
|
|
|
|
|
resp, err := http.ReadResponse(bufferedReader, nil)
|
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
data, err := ioutil.ReadAll(resp.Body)
|
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
require.Equal(t, resp.StatusCode, code)
|
|
|
|
|
require.Equal(t, data, []byte(`some data`))
|
|
|
|
|
resp.Body.Close()
|
|
|
|
|
// Send upgrade request resulting in a non-101 response from the backend
|
|
|
|
|
req, _ := http.NewRequest("GET", "/", nil)
|
|
|
|
|
req.Header.Set(httpstream.HeaderConnection, httpstream.HeaderUpgrade)
|
|
|
|
|
require.NoError(t, req.Write(conn))
|
|
|
|
|
// Verify we get the correct response and full message body content
|
|
|
|
|
resp, err := http.ReadResponse(bufferedReader, nil)
|
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
data, err := ioutil.ReadAll(resp.Body)
|
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
require.Equal(t, resp.StatusCode, code)
|
|
|
|
|
require.Equal(t, data, []byte(`some data`))
|
|
|
|
|
resp.Body.Close()
|
|
|
|
|
|
|
|
|
|
// try to read from the connection to verify it was closed
|
|
|
|
|
b := make([]byte, 1)
|
|
|
|
|
conn.SetReadDeadline(time.Now().Add(time.Second))
|
|
|
|
|
if _, err := conn.Read(b); err != io.EOF {
|
|
|
|
|
t.Errorf("expected EOF, got %v", err)
|
|
|
|
|
}
|
|
|
|
|
// try to read from the connection to verify it was closed
|
|
|
|
|
b := make([]byte, 1)
|
|
|
|
|
conn.SetReadDeadline(time.Now().Add(time.Second))
|
|
|
|
|
if _, err := conn.Read(b); err != io.EOF {
|
|
|
|
|
t.Errorf("expected EOF, got %v", err)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Send another request to another endpoint to verify it is not received
|
|
|
|
|
req, _ = http.NewRequest("GET", "/there", nil)
|
|
|
|
|
req.Write(conn)
|
|
|
|
|
// wait to ensure the handler does not receive the request
|
|
|
|
|
time.Sleep(time.Second)
|
|
|
|
|
// Send another request to another endpoint to verify it is not received
|
|
|
|
|
req, _ = http.NewRequest("GET", "/there", nil)
|
|
|
|
|
req.Write(conn)
|
|
|
|
|
// wait to ensure the handler does not receive the request
|
|
|
|
|
time.Sleep(time.Second)
|
|
|
|
|
|
|
|
|
|
// clean up
|
|
|
|
|
conn.Close()
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
// clean up
|
|
|
|
|
conn.Close()
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestProxyUpgradeErrorResponse(t *testing.T) {
|
|
|
|
|
for _, intercept := range []bool{true, false} {
|
|
|
|
|
for _, code := range []int{200, 300, 302, 307} {
|
|
|
|
|
t.Run(fmt.Sprintf("intercept=%v,code=%v", intercept, code), func(t *testing.T) {
|
|
|
|
|
// Set up a backend server
|
|
|
|
|
backend := http.NewServeMux()
|
|
|
|
|
backend.Handle("/hello", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
|
|
|
http.Redirect(w, r, "https://example.com/there", code)
|
|
|
|
|
}))
|
|
|
|
|
backendServer := httptest.NewServer(backend)
|
|
|
|
|
defer backendServer.Close()
|
|
|
|
|
backendServerURL, _ := url.Parse(backendServer.URL)
|
|
|
|
|
backendServerURL.Path = "/hello"
|
|
|
|
|
for _, code := range []int{200, 300, 302, 307} {
|
|
|
|
|
t.Run(fmt.Sprintf("code=%v", code), func(t *testing.T) {
|
|
|
|
|
// Set up a backend server
|
|
|
|
|
backend := http.NewServeMux()
|
|
|
|
|
backend.Handle("/hello", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
|
|
|
http.Redirect(w, r, "https://example.com/there", code)
|
|
|
|
|
}))
|
|
|
|
|
backendServer := httptest.NewServer(backend)
|
|
|
|
|
defer backendServer.Close()
|
|
|
|
|
backendServerURL, _ := url.Parse(backendServer.URL)
|
|
|
|
|
backendServerURL.Path = "/hello"
|
|
|
|
|
|
|
|
|
|
// Set up a proxy pointing to a specific path on the backend
|
|
|
|
|
proxyHandler := NewUpgradeAwareHandler(backendServerURL, nil, false, false, &fakeResponder{t: t})
|
|
|
|
|
proxyHandler.InterceptRedirects = intercept
|
|
|
|
|
proxyHandler.RequireSameHostRedirects = true
|
|
|
|
|
proxy := httptest.NewServer(proxyHandler)
|
|
|
|
|
defer proxy.Close()
|
|
|
|
|
proxyURL, _ := url.Parse(proxy.URL)
|
|
|
|
|
// Set up a proxy pointing to a specific path on the backend
|
|
|
|
|
proxyHandler := NewUpgradeAwareHandler(backendServerURL, nil, false, false, &fakeResponder{t: t})
|
|
|
|
|
proxy := httptest.NewServer(proxyHandler)
|
|
|
|
|
defer proxy.Close()
|
|
|
|
|
proxyURL, _ := url.Parse(proxy.URL)
|
|
|
|
|
|
|
|
|
|
conn, err := net.Dial("tcp", proxyURL.Host)
|
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
bufferedReader := bufio.NewReader(conn)
|
|
|
|
|
conn, err := net.Dial("tcp", proxyURL.Host)
|
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
bufferedReader := bufio.NewReader(conn)
|
|
|
|
|
|
|
|
|
|
// Send upgrade request resulting in a non-101 response from the backend
|
|
|
|
|
req, _ := http.NewRequest("GET", "/", nil)
|
|
|
|
|
req.Header.Set(httpstream.HeaderConnection, httpstream.HeaderUpgrade)
|
|
|
|
|
require.NoError(t, req.Write(conn))
|
|
|
|
|
// Verify we get the correct response and full message body content
|
|
|
|
|
resp, err := http.ReadResponse(bufferedReader, nil)
|
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
assert.Equal(t, fakeStatusCode, resp.StatusCode)
|
|
|
|
|
resp.Body.Close()
|
|
|
|
|
// Send upgrade request resulting in a non-101 response from the backend
|
|
|
|
|
req, _ := http.NewRequest("GET", "/", nil)
|
|
|
|
|
req.Header.Set(httpstream.HeaderConnection, httpstream.HeaderUpgrade)
|
|
|
|
|
require.NoError(t, req.Write(conn))
|
|
|
|
|
// Verify we get the correct response and full message body content
|
|
|
|
|
resp, err := http.ReadResponse(bufferedReader, nil)
|
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
assert.Equal(t, fakeStatusCode, resp.StatusCode)
|
|
|
|
|
resp.Body.Close()
|
|
|
|
|
|
|
|
|
|
// clean up
|
|
|
|
|
conn.Close()
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
// clean up
|
|
|
|
|
conn.Close()
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|