Repository: seanmonstar/warp (language: rust)

Issue:
Allow construction of websocket pong messages
**Is your feature request related to a problem? Please describe.**
I am writing websocket server and I'm mocking the `warp::filters::ws::WebSocket` with a custom type implementing `Sink<Message>` and `Stream<Item=Result<Message, Error>>`. To be able to test the timeout behavior of the code I need to manually respond to Ping messages with a Pong message. Currently the API doesn't provide a way to construct a Pong message.

**Describe the solution you'd like**
I'd like to be able to construct a [`Message`](https://docs.rs/warp/0.2.5/warp/filters/ws/struct.Message.html) representing a pong message. The API could be very similar to the existing `ping` function. For example the following (untested) code could be used:
```rust
/// Construct a new Pong `Message`.
///
/// Note that this is rarely needed as Ping messages are automatically responded with the corresponding Pong message by
/// the underlying socket. This is mainly provided for some unconventional use cases, like writing mock implementations
/// for tests
pub fn pong<V: Into<Vec<u8>>>(v: V) -> Message {
    Message {
        inner: protocol::Message::Pong(v.into()),
    }
}
```

**Describe alternatives you've considered**
An alternative could be to provide a `From` implementation for `tungstenite::protocol::Message`.



Discussion / hints:
Would it help if I created a PR with the proposed code? Or should I wait for a comment from the maintainer?
Hi, yeah you can go ahead and submit a PR :)

Fix patch:
diff --git a/src/filters/ws.rs b/src/filters/ws.rs
index 956cfe4ea..2bf79a20a 100644
--- a/src/filters/ws.rs
+++ b/src/filters/ws.rs
@@ -291,6 +291,17 @@ impl Message {
         }
     }
 
+    /// Construct a new Pong `Message`.
+    ///
+    /// Note that one rarely needs to manually construct a Pong message because the underlying tungstenite socket
+    /// automatically responds to the Ping messages it receives. Manual construction might still be useful in some cases
+    /// like in tests or to send unidirectional heartbeats.
+    pub fn pong<V: Into<Vec<u8>>>(v: V) -> Message {
+        Message {
+            inner: protocol::Message::Pong(v.into()),
+        }
+    }
+
     /// Construct the default Close `Message`.
     pub fn close() -> Message {
         Message {


Test patch:
diff --git a/tests/ws.rs b/tests/ws.rs
index 052a195f4..1667da927 100644
--- a/tests/ws.rs
+++ b/tests/ws.rs
@@ -149,6 +149,28 @@ async fn echo_pings() {
     assert_eq!(msg.as_bytes(), &b"clt"[..]);
 }
 
+#[tokio::test]
+async fn pongs_only() {
+    let _ = pretty_env_logger::try_init();
+
+    let mut client = warp::test::ws()
+        .handshake(ws_echo())
+        .await
+        .expect("handshake");
+
+    // construct a pong message and make sure it is correct
+    let msg = Message::pong("clt");
+    assert!(msg.is_pong());
+    assert_eq!(msg.as_bytes(), &b"clt"[..]);
+
+    // send it to echo and wait for `ws_echo` to send it back
+    client.send(msg).await;
+
+    let msg = client.recv().await.expect("recv");
+    assert!(msg.is_pong());
+    assert_eq!(msg.as_bytes(), &b"clt"[..]);
+}
+
 #[tokio::test]
 async fn closed() {
     let _ = pretty_env_logger::try_init();