stream-tungstenite
A robust Rust WebSocket client library with automatic reconnection, customizable retry strategies, and an extensible architecture.
Features
- Automatic Reconnection: Multiple retry strategies including exponential backoff
- Connection State Management: Real-time tracking of connection status and health
- Extension System: Hook into lifecycle events and message processing
- Application-Level Handshakes: Support for authentication and subscriptions
- Builder Pattern API: Fluent, type-safe configuration
- Backpressure-Aware Sending: Bounded send queue with non-blocking, blocking, and timeout APIs
Architecture
┌─────────────────────────────────────────────────────────────────┐
│ WebSocketClient │
│ - High-level API for WebSocket connections │
│ - Automatic reconnection with retry strategies │
│ - Message broadcasting via channels │
└─────────────────────────────────────────────────────────────────┘
│
┌───────────────────┼───────────────────┐
▼ ▼ ▼
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ Handshake │ │ Extension │ │ Connection │
│ - Auth │ │ - Lifecycle │ │ - State │
│ - Subscribe │ │ - Messages │ │ - Retry │
│ - Chained │ │ - Logging │ │ - Supervisor │
└─────────────────┘ └─────────────────┘ └─────────────────┘
Quick Start
Basic Usage
use *;
use Arc;
async
Sending Messages
use *;
use Arc;
use Message;
async
Backpressure and Timeout
- Non-blocking (default):
client.send(msg).await
Returns immediately; if the queue is full, returnsSendError::ChannelFull. - Blocking:
client.send_async(msg).await
Awaits capacity; returnsSendError::ChannelClosedif not connected. - Timeout:
client.send_timeout(msg, Duration::from_secs(1)).await
ReturnsSendError::Timeout(_)if it expires.
Configure queue capacity:
let cfg = new.with_send_queue_capacity;
Configure handshake retry delay:
let cfg = new.with_handshake_retry_delay;
Configuration
Using ClientConfig
use *;
use Duration;
// Create custom configuration
let config = new
.with_receive_timeout
.with_exit_on_first_failure
.with_nodelay
.with_channel_buffer;
let client = builder
.config
.build;
Configuration Presets
The library provides preset configurations for common scenarios:
Fast Reconnect
For low-latency scenarios requiring quick recovery:
let config = fast_reconnect;
// - Receive timeout: 10 seconds
// - Connect timeout: 10 seconds
// - Nagle disabled: true
// - Channel buffer: 512
Stable Connection
For long-running, stable connections:
let config = stable_connection;
// - Receive timeout: 60 seconds
// - Connect timeout: 60 seconds
// - Nagle disabled: false
// - Channel buffer: 128
Retry Strategies
Exponential Backoff (Default)
use *;
use Duration;
let client = builder
.exponential_backoff
.build;
Preset Strategies
// Fast reconnection - quick recovery
let strategy = fast;
// - 100ms initial, 5s max, 1.5x factor
// Standard - balanced approach
let strategy = standard;
// - 1s initial, 60s max, 2x factor
// Conservative - longer waits
let strategy = conservative;
// - 2s initial, 120s max, 2x factor
Fixed Delay
use *;
use Duration;
let strategy = new
.with_max_attempts;
let client = builder
.retry_strategy
.build;
No Retry
let client = builder
.no_retry
.build;
Handshakes
Perform application-level handshakes after WebSocket connection is established.
Authentication
use *;
// Plain text token
let auth = new;
// JSON format: {"type":"auth","token":"..."}
let auth = new.json;
// Custom format
let auth = new
.custom_format;
let client = builder
.handshaker
.build;
Connection Timeout and Handshake Retry
use *;
use Duration;
let cfg = new
.with_connect_timeout // TCP/WebSocket connect timeout
.with_handshake_retry_delay; // wait before retrying failed handshakes
Extension Message Processing (Processor)
Extensions can transform or filter messages; the dispatcher applies them before broadcasting:
use async_trait;
use Extension;
use ConnectionContext;
use Message;
;
Channel Subscription
use *;
let subscribe = new
.wait_confirmation;
let client = builder
.handshaker
.build;
Chained Handshakes
use *;
// Chain multiple handshakers
let handshaker = new
.then
.then;
let client = builder
.handshaker
.build;
// Or use the macro
let handshaker = chain_handshakers!;
Extension System
Add custom functionality through the extension system.
Built-in Extensions
Logging Extension
use *;
// Basic logging
let logging = new;
// Verbose with message logging
let logging = verbose;
// Custom configuration
let config = new
.with_level
.with_messages
.with_prefix;
let logging = with_config;
// Register with client
client.register_extension.await?;
Status Viewer
use *;
let status = new;
// Check connection status
if status.is_connected.await
// Advanced status with history
let advanced = new;
let uptime = advanced.get_uptime.await;
let connection_count = advanced.get_connection_count.await;
Custom Extensions
use Extension;
use ConnectionContext;
use ExtensionError;
use async_trait;
use Message;
;
Connection Events
Monitor connection state changes:
use *;
use Arc;
async
Connection State
Access detailed connection state:
// Get current state snapshot
let state = client.state.await;
println!;
println!;
println!;
println!;
if let Some = state.connection_duration
// Quick connection check
if client.is_connected
Error Handling
The library provides structured error types:
use *;
// Top-level errors
match client.run.await
// Connection errors include retryability info
let error = TcpFailed;
if error.is_retryable
TLS Configuration
The library supports multiple TLS backends via feature flags. Choose one based on your requirements:
Available TLS Features
[]
# Default: native-tls (system TLS, cross-platform)
= "0.6"
# Rustls with system certificates (pure Rust, recommended)
= { = "0.6", = false, = ["rustls-tls-native-roots"] }
# Rustls with embedded certificates (no system dependency)
= { = "0.6", = false, = ["rustls-tls-webpki-roots"] }
# Native TLS with vendored dependencies (for static linking)
= { = "0.6", = false, = ["native-tls-vendored"] }
Custom TLS Configuration
Complete Control with TLS Connector
use *;
use Connector;
// Native TLS example
// Rustls example
Disable Certificate Verification (Testing Only!)
Security Warning: Never use in production!
use *;
// For testing with self-signed certificates
let connector = new
.danger_accept_invalid_certs?;
let client = builder
.connector
.build;
Custom CA Certificates
use *;
Client Certificate Authentication (mTLS)
use *;
TLS Feature Comparison
| Feature | native-tls | rustls-tls-native-roots | rustls-tls-webpki-roots |
|---|---|---|---|
| Backend | System (OpenSSL/Security.framework/SChannel) | Pure Rust | Pure Rust |
| System Certs | ✅ Yes | ✅ Yes | ❌ No (embedded) |
| Binary Size | Smaller | Medium | Medium |
| Cross-compile | Harder | Easier | Easier |
| FIPS | Depends on system | ❌ No | ❌ No |
| Performance | Good | Excellent | Excellent |
Recommendation: Use rustls-tls-native-roots for most projects (better security, pure Rust). Use native-tls if you need system certificate stores or FIPS compliance.
Installation
Add to your Cargo.toml:
[]
= "0.6"
= { = "1.0", = ["full"] }
License
This project is licensed under the Apache License Version 2.0. See the LICENSE file for details.
Contributing
Contributions are welcome! Please feel free to submit Pull Requests or create Issues.