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}