mirror of
				https://github.com/caddyserver/caddy.git
				synced 2025-11-03 19:17:29 -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
					
				@ -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)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		pooledIoCopy(backendConn, conn)
 | 
							go func() {
 | 
				
			||||||
 | 
								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…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user