websockets/
lib.rs

1//! A WebSocket client implementation.
2//!
3//! [<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)
4//!
5//! ```rust
6//! # use websockets::WebSocketError;
7//! use websockets::WebSocket;
8//!
9//! # #[tokio::main]
10//! # async fn main() -> Result<(), WebSocketError> {
11//! let mut ws = WebSocket::connect("wss://echo.websocket.org/").await?;
12//! ws.send_text("foo".to_string()).await?;
13//! ws.receive().await?;
14//! ws.close(None).await?;
15//! # Ok(())
16//! # }
17//! ```
18//!
19//! ## Features
20//!
21//! * Simple API
22//! * Async/await (tokio runtime)
23//! * TLS support (automatically detected)
24//!
25//! ## Usage
26//!
27//! The [`WebSocket`] type manages the WebSocket connection.
28//! Use it to connect, send, and receive data.
29//! Data is sent and received through [`Frame`]s.
30//!
31//! ## License
32//!
33//! This project is licensed under the MIT license.
34
35#![forbid(
36    unsafe_code,
37    missing_debug_implementations,
38    missing_docs,
39    missing_debug_implementations
40)]
41
42mod error;
43pub mod secure;
44mod websocket;
45
46pub use error::WebSocketError;
47pub use websocket::frame::Frame;
48pub use websocket::split::{WebSocketReadHalf, WebSocketWriteHalf};
49pub use websocket::{builder::WebSocketBuilder, WebSocket};
50
51#[cfg(test)]
52mod tests {
53    use crate::*;
54
55    #[tokio::test]
56    async fn echo_length_0_to_125() {
57        let mut ws = WebSocket::connect("ws://echo.websocket.org/")
58            .await
59            .unwrap();
60        let message = "a".repeat(3).to_string();
61        ws.send_text(message.clone()).await.unwrap();
62        let received_frame = ws.receive().await.unwrap();
63        let received_message = received_frame.as_text().unwrap().0.clone();
64        assert_eq!(message, received_message);
65    }
66
67    #[tokio::test]
68    async fn echo_length_126_to_u16_max() {
69        let mut ws = WebSocket::connect("ws://echo.websocket.org/")
70            .await
71            .unwrap();
72        let message = "a".repeat(300).to_string();
73        ws.send_text(message.clone()).await.unwrap();
74        let received_frame = ws.receive().await.unwrap();
75        let received_message = received_frame.as_text().unwrap().0.clone();
76        assert_eq!(message, received_message);
77    }
78
79    #[tokio::test]
80    async fn echo_length_u16_max_to_u64_max() {
81        let mut ws = WebSocket::connect("ws://echo.websocket.org/")
82            .await
83            .unwrap();
84        let message = "a".repeat(66000).to_string();
85        ws.send_text(message.clone()).await.unwrap();
86        let received_frame = ws.receive().await.unwrap();
87        let received_message = received_frame.as_text().unwrap().0.clone();
88        assert_eq!(message, received_message);
89    }
90
91    #[tokio::test]
92    async fn echo_tls() {
93        let mut ws = WebSocket::connect("wss://echo.websocket.org/")
94            .await
95            .unwrap();
96        let message = "a".repeat(66000).to_string();
97        ws.send_text(message.clone()).await.unwrap();
98        let received_frame = ws.receive().await.unwrap();
99        let received_message = received_frame.as_text().unwrap().0.clone();
100        assert_eq!(message, received_message);
101    }
102
103    #[tokio::test]
104    async fn close() {
105        let mut ws = WebSocket::connect("wss://echo.websocket.org")
106            .await
107            .unwrap();
108        ws.close(Some((1000, String::new()))).await.unwrap();
109        let status_code = ws.receive().await.unwrap().as_close().unwrap().0;
110        assert_eq!(status_code, 1000);
111    }
112
113    #[tokio::test]
114    async fn bad_scheme() {
115        let resp = WebSocket::connect("http://echo.websocket.org").await;
116        if let Ok(_) = resp {
117            panic!("expected to fail with bad scheme");
118        }
119    }
120}