seanmonstar / warp

A super-easy, composable, web server framework for warp speeds.
https://seanmonstar.com/post/176530511587/warp
MIT License
9.57k stars 719 forks source link

WebSocket doesn't close properly if network connection is abruptly cut off #798

Open indianakernick opened 3 years ago

indianakernick commented 3 years ago

Version

warp v0.3.0

Platform

macOS 10.14.6

Description I'm noticing something odd happening when websockets are disconnected. It seems as though the end of the function called inside on_upgrade isn't always reached when the socket is disconnected. I'm talking about this line from the example. Sometimes the socket is disconnected without reaching that line.

The trouble is, this only happens sometimes. It's rare but just often enough for me to notice. I don't know how to reproduce it so maybe this can't be fixed. My code is pretty similar in structure to the example. I'm wondering, is there some way for the socket to be disconnected without reaching that line?


After some investigation. This seems to happen when the network connection is abruptly cut off. I'm able to consistently reproduce this problem whenever I cut the connection. I'm using a modified version of the websocket example:

use futures::{FutureExt, StreamExt};
use warp::Filter;

#[tokio::main]
async fn main() {
    pretty_env_logger::init();

    let routes = warp::path("socket")
        // The `ws()` filter will prepare the Websocket handshake.
        .and(warp::ws())
        .map(|ws: warp::ws::Ws| {
            // And then our closure will be called when it completes...
            ws.on_upgrade(|websocket| {
                async {
                    println!("Connected");
                    // Just echo all messages back...
                    let (tx, rx) = websocket.split();
                    rx.forward(tx).map(|result| {
                        if let Err(e) = result {
                            eprintln!("websocket error: {:?}", e);
                        }
                    }).await;
                    println!("Disconnected");
                }
            })
        });

    warp::serve(routes).run(([0, 0, 0, 0], 80)).await;
}

If the client disconnects gracefully, the Disconnected message is printed (along with Connection reset without closing handshake). If the network connection is cut, nothing is printed.

skifli commented 4 weeks ago

Hey, are there any updates to this? I used a temporary fix by adding heartbeats to my websocket (akin to how Discord's gateway functions), but I feel like it would be best if this was addressed on the library's side.