1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
//! A WebSocket client implementation.
//! 
//! [<img alt="github" src="https://img.shields.io/badge/github-imranmaj/websockets-6bb858?style=for-the-badge&logo=github">](https://github.com/imranmaj/websockets) [<img alt="crates.io" src="https://img.shields.io/crates/v/websockets.svg?style=for-the-badge&color=e38e17&logo=rust">](https://crates.io/crates/websockets) [<img alt="docs.rs" src="https://img.shields.io/badge/docs.rs-websockets-6f83f2?style=for-the-badge&logo=data:image/svg+xml;base64,PHN2ZyByb2xlPSJpbWciIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDUxMiA1MTIiPjxwYXRoIGZpbGw9IiNmNWY1ZjUiIGQ9Ik00ODguNiAyNTAuMkwzOTIgMjE0VjEwNS41YzAtMTUtOS4zLTI4LjQtMjMuNC0zMy43bC0xMDAtMzcuNWMtOC4xLTMuMS0xNy4xLTMuMS0yNS4zIDBsLTEwMCAzNy41Yy0xNC4xIDUuMy0yMy40IDE4LjctMjMuNCAzMy43VjIxNGwtOTYuNiAzNi4yQzkuMyAyNTUuNSAwIDI2OC45IDAgMjgzLjlWMzk0YzAgMTMuNiA3LjcgMjYuMSAxOS45IDMyLjJsMTAwIDUwYzEwLjEgNS4xIDIyLjEgNS4xIDMyLjIgMGwxMDMuOS01MiAxMDMuOSA1MmMxMC4xIDUuMSAyMi4xIDUuMSAzMi4yIDBsMTAwLTUwYzEyLjItNi4xIDE5LjktMTguNiAxOS45LTMyLjJWMjgzLjljMC0xNS05LjMtMjguNC0yMy40LTMzLjd6TTM1OCAyMTQuOGwtODUgMzEuOXYtNjguMmw4NS0zN3Y3My4zek0xNTQgMTA0LjFsMTAyLTM4LjIgMTAyIDM4LjJ2LjZsLTEwMiA0MS40LTEwMi00MS40di0uNnptODQgMjkxLjFsLTg1IDQyLjV2LTc5LjFsODUtMzguOHY3NS40em0wLTExMmwtMTAyIDQxLjQtMTAyLTQxLjR2LS42bDEwMi0zOC4yIDEwMiAzOC4ydi42em0yNDAgMTEybC04NSA0Mi41di03OS4xbDg1LTM4Ljh2NzUuNHptMC0xMTJsLTEwMiA0MS40LTEwMi00MS40di0uNmwxMDItMzguMiAxMDIgMzguMnYuNnoiPjwvcGF0aD48L3N2Zz4K">](https://docs.rs/websockets)
//!
//! ```rust
//! use websockets::{WebSocket, WebSocketError};
//! 
//! #[tokio::main]
//! async fn main() {
//!     let mut ws = WebSocket::connect("wss://echo.websocket.org/").await.unwrap();
//!     ws.send_text("foo".to_string(), false, true).await.unwrap();
//!     ws.receive().await.unwrap();
//!     ws.close(None).await.unwrap();
//! }
//! ```
//! 
//! ## Usage
//! 
//! The [`WebSocket`] type manages the WebSocket connection. 
//! Use it to connect, send, and receive data. 
//! Data is sent and received through [`Frame`]s.
//! 
//! See these types for additional information on how to use them.

#![forbid(
    unsafe_code,
    missing_debug_implementations,
    missing_crate_level_docs,
    missing_docs
)]

mod error;
mod websocket;

pub use error::WebSocketError;
pub use websocket::frame::Frame;
pub use websocket::{builder::WebSocketBuilder, WebSocket};

#[cfg(test)]
mod tests {
    use crate::*;

    #[tokio::test]
    async fn echo_length_0_to_125() {
        let mut ws = WebSocket::connect("ws://echo.websocket.org/")
            .await
            .unwrap();
        let message = "a".repeat(3).to_string();
        ws.send_text(message.clone(), false, true).await.unwrap();
        let received_frame = ws.receive().await.unwrap();
        let received_message = received_frame.as_text().unwrap().0.clone();
        assert_eq!(message, received_message);
    }

    #[tokio::test]
    async fn echo_length_126_to_u16_max() {
        let mut ws = WebSocket::connect("ws://echo.websocket.org/")
            .await
            .unwrap();
        let message = "a".repeat(300).to_string();
        ws.send_text(message.clone(), false, true).await.unwrap();
        let received_frame = ws.receive().await.unwrap();
        let received_message = received_frame.as_text().unwrap().0.clone();
        assert_eq!(message, received_message);
    }

    #[tokio::test]
    async fn echo_length_u16_max_to_u64_max() {
        let mut ws = WebSocket::connect("ws://echo.websocket.org/")
            .await
            .unwrap();
        let message = "a".repeat(66000).to_string();
        ws.send_text(message.clone(), false, true).await.unwrap();
        let received_frame = ws.receive().await.unwrap();
        let received_message = received_frame.as_text().unwrap().0.clone();
        assert_eq!(message, received_message);
    }

    #[tokio::test]
    async fn echo_tls() {
        let mut ws = WebSocket::connect("wss://echo.websocket.org/")
            .await
            .unwrap();
        let message = "a".repeat(66000).to_string();
        ws.send_text(message.clone(), false, true).await.unwrap();
        let received_frame = ws.receive().await.unwrap();
        let received_message = received_frame.as_text().unwrap().0.clone();
        assert_eq!(message, received_message);
    }

    #[tokio::test]
    async fn close() {
        let mut ws = WebSocket::connect("wss://echo.websocket.org")
            .await
            .unwrap();
        let status_code = ws
            .close(Some((1000, String::new())))
            .await
            .unwrap()
            .as_close()
            .unwrap()
            .0;
        assert_eq!(status_code, 1000);
    }

    #[tokio::test]
    async fn bad_scheme() {
        let resp = WebSocket::connect("http://echo.websocket.org").await;
        if let Ok(_) = resp {
            panic!("expected to fail with bad scheme");
        }
    }
}