mirror of
https://github.com/caddyserver/caddy.git
synced 2024-12-23 22:27:38 -05:00
proxy: websocket proxy exits immediately if backend is shutdown (#1869)
Signed-off-by: Tw <tw19881113@gmail.com>
This commit is contained in:
parent
84a2f8e89e
commit
e377eeff50
2 changed files with 47 additions and 2 deletions
|
@ -304,6 +304,40 @@ func TestWebSocketReverseProxyNonHijackerPanic(t *testing.T) {
|
||||||
p.ServeHTTP(nonHijacker, r)
|
p.ServeHTTP(nonHijacker, r)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestWebSocketReverseProxyBackendShutDown(t *testing.T) {
|
||||||
|
shutdown := make(chan struct{})
|
||||||
|
backend := httptest.NewServer(websocket.Handler(func(ws *websocket.Conn) {
|
||||||
|
shutdown <- struct{}{}
|
||||||
|
}))
|
||||||
|
defer backend.Close()
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
<-shutdown
|
||||||
|
backend.Close()
|
||||||
|
}()
|
||||||
|
|
||||||
|
// Get proxy to use for the test
|
||||||
|
p := newWebSocketTestProxy(backend.URL, false)
|
||||||
|
backendProxy := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
p.ServeHTTP(w, r)
|
||||||
|
}))
|
||||||
|
defer backendProxy.Close()
|
||||||
|
|
||||||
|
// Set up WebSocket client
|
||||||
|
url := strings.Replace(backendProxy.URL, "http://", "ws://", 1)
|
||||||
|
ws, err := websocket.Dial(url, "", backendProxy.URL)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer ws.Close()
|
||||||
|
|
||||||
|
var actualMsg string
|
||||||
|
if rcvErr := websocket.Message.Receive(ws, &actualMsg); rcvErr == nil {
|
||||||
|
t.Errorf("we don't get backend shutdown notification")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestWebSocketReverseProxyServeHTTPHandler(t *testing.T) {
|
func TestWebSocketReverseProxyServeHTTPHandler(t *testing.T) {
|
||||||
// No-op websocket backend simply allows the WS connection to be
|
// No-op websocket backend simply allows the WS connection to be
|
||||||
// accepted then it will be immediately closed. Perfect for testing.
|
// accepted then it will be immediately closed. Perfect for testing.
|
||||||
|
|
|
@ -320,8 +320,13 @@ func (rp *ReverseProxy) ServeHTTP(rw http.ResponseWriter, outreq *http.Request,
|
||||||
}
|
}
|
||||||
defer backendConn.Close()
|
defer backendConn.Close()
|
||||||
|
|
||||||
|
proxyDone := make(chan struct{}, 2)
|
||||||
|
|
||||||
// Proxy backend -> frontend.
|
// Proxy backend -> frontend.
|
||||||
go pooledIoCopy(conn, backendConn)
|
go func() {
|
||||||
|
pooledIoCopy(conn, backendConn)
|
||||||
|
proxyDone <- struct{}{}
|
||||||
|
}()
|
||||||
|
|
||||||
// Proxy frontend -> backend.
|
// Proxy frontend -> backend.
|
||||||
//
|
//
|
||||||
|
@ -336,7 +341,13 @@ func (rp *ReverseProxy) ServeHTTP(rw http.ResponseWriter, outreq *http.Request,
|
||||||
backendConn.Write(rbuf)
|
backendConn.Write(rbuf)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
go func() {
|
||||||
pooledIoCopy(backendConn, conn)
|
pooledIoCopy(backendConn, conn)
|
||||||
|
proxyDone <- struct{}{}
|
||||||
|
}()
|
||||||
|
|
||||||
|
// If one side is done, we are done.
|
||||||
|
<-proxyDone
|
||||||
} else {
|
} else {
|
||||||
// NOTE:
|
// NOTE:
|
||||||
// Closing the Body involves acquiring a mutex, which is a
|
// Closing the Body involves acquiring a mutex, which is a
|
||||||
|
|
Loading…
Reference in a new issue