circles/examples/wss_test_client.rs
2025-07-08 22:49:47 +02:00

136 lines
4.7 KiB
Rust

//! WSS Test Client
//!
//! This example demonstrates connecting to a WSS server for testing purposes.
//! It's a simple client that connects to the WSS server and sends a test message.
//!
//! Usage: cargo run --manifest-path src/server/Cargo.toml --example wss_test_client
use tokio_tungstenite::{connect_async_tls_with_config, Connector};
use tokio_tungstenite::tungstenite::protocol::Message;
use futures_util::{SinkExt, StreamExt};
use log::{info, warn, error};
use std::time::Duration;
use tokio::time::timeout;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Initialize logging
env_logger::init();
info!("🧪 Starting WSS Test Client");
info!("🔗 Attempting to connect to wss://127.0.0.1:8443/ws");
// Create a TLS connector that accepts self-signed certificates for testing
let connector = Connector::NativeTls(
native_tls::TlsConnector::builder()
.danger_accept_invalid_certs(true)
.danger_accept_invalid_hostnames(true)
.build()
.map_err(|e| format!("TLS connector error: {}", e))?
);
let config = Some(tokio_tungstenite::tungstenite::protocol::WebSocketConfig {
max_send_queue: None,
max_message_size: Some(64 << 20), // 64 MB
max_frame_size: Some(16 << 20), // 16 MB
accept_unmasked_frames: false,
});
// Connect to the WSS server
info!("🔌 Connecting to WSS server...");
let connect_result = timeout(
Duration::from_secs(10),
connect_async_tls_with_config(
"wss://127.0.0.1:8443/ws",
config,
false,
Some(connector)
)
).await;
let (ws_stream, response) = match connect_result {
Ok(Ok((stream, response))) => {
info!("✅ Successfully connected to WSS server!");
info!("📡 Response status: {}", response.status());
(stream, response)
}
Ok(Err(e)) => {
error!("❌ Failed to connect to WSS server: {}", e);
return Err(format!("Connection failed: {}", e).into());
}
Err(_) => {
error!("❌ Connection timeout after 10 seconds");
return Err("Connection timeout".into());
}
};
let (mut ws_sender, mut ws_receiver) = ws_stream.split();
// Send a test JSON-RPC message
let test_message = serde_json::json!({
"jsonrpc": "2.0",
"method": "fetch_nonce",
"params": {
"pubkey": "test_public_key_123"
},
"id": 1
});
info!("📤 Sending test message: {}", test_message);
ws_sender.send(Message::Text(test_message.to_string())).await
.map_err(|e| format!("Send error: {}", e))?;
// Wait for response
info!("⏳ Waiting for server response...");
let response_result = timeout(Duration::from_secs(5), ws_receiver.next()).await;
match response_result {
Ok(Some(Ok(Message::Text(response)))) => {
info!("📥 Received response: {}", response);
// Parse the JSON response
match serde_json::from_str::<serde_json::Value>(&response) {
Ok(json_response) => {
if json_response.get("result").is_some() {
info!("✅ Server responded with valid JSON-RPC result");
info!("🎉 WSS connection and communication test PASSED!");
} else if json_response.get("error").is_some() {
warn!("⚠️ Server responded with error (expected for unauthenticated request)");
info!("✅ WSS connection test PASSED (server is responding correctly)");
} else {
warn!("⚠️ Unexpected response format");
}
}
Err(e) => {
warn!("⚠️ Failed to parse JSON response: {}", e);
}
}
}
Ok(Some(Ok(message))) => {
info!("📥 Received non-text message: {:?}", message);
}
Ok(Some(Err(e))) => {
error!("❌ WebSocket error: {}", e);
return Err(format!("WebSocket error: {}", e).into());
}
Ok(None) => {
warn!("⚠️ Connection closed by server");
}
Err(_) => {
error!("❌ Response timeout after 5 seconds");
return Err("Response timeout".into());
}
}
// Close the connection
info!("🔌 Closing WSS connection...");
ws_sender.close().await
.map_err(|e| format!("Close error: {}", e))?;
info!("✅ WSS Test Client completed successfully!");
Ok(())
}