@@ -1858,11 +1858,34 @@ impl ProxyService {
18581858 Ok ( close_frame) => {
18591859 tracing:: debug!( "websocket handler complete, closing" ) ;
18601860
1861- // Send graceful close
1862- ws_handle. send ( to_hyper_close ( close_frame) ) . await ?;
1861+ // Send graceful close. This may fail if client already sent
1862+ // close frame, which is normal.
1863+ tracing:: debug!( ?close_frame, "sending close frame to client" ) ;
1864+ match ws_handle. send ( to_hyper_close ( close_frame) ) . await {
1865+ Ok ( _) => {
1866+ tracing:: debug!( "close frame sent successfully" ) ;
1867+ }
1868+ Err ( err) => {
1869+ tracing:: debug!(
1870+ ?err,
1871+ "failed to send close frame (websocket may be already closing)"
1872+ ) ;
1873+ }
1874+ }
18631875
18641876 // Flush to ensure close frame is sent
1865- ws_handle. flush ( ) . await ?;
1877+ tracing:: debug!( "flushing websocket" ) ;
1878+ match ws_handle. flush ( ) . await {
1879+ Ok ( _) => {
1880+ tracing:: debug!( "websocket flushed successfully" ) ;
1881+ }
1882+ Err ( err) => {
1883+ tracing:: debug!(
1884+ ?err,
1885+ "failed to flush websocket (websocket may be already closing)"
1886+ ) ;
1887+ }
1888+ }
18661889
18671890 // Keep TCP connection open briefly to allow client to process close
18681891 tokio:: time:: sleep ( WEBSOCKET_CLOSE_LINGER ) . await ;
@@ -2541,6 +2564,11 @@ fn to_hyper_close(frame: Option<CloseFrame>) -> hyper_tungstenite::tungstenite::
25412564 } ,
25422565 ) )
25432566 } else {
2544- tokio_tungstenite:: tungstenite:: Message :: Close ( None )
2567+ tokio_tungstenite:: tungstenite:: Message :: Close ( Some (
2568+ tokio_tungstenite:: tungstenite:: protocol:: CloseFrame {
2569+ code : CloseCode :: Normal ,
2570+ reason : "ws.closed" . into ( ) ,
2571+ } ,
2572+ ) )
25452573 }
25462574}
0 commit comments