-
Notifications
You must be signed in to change notification settings - Fork 5
Expand file tree
/
Copy pathclient-callback.rs
More file actions
85 lines (72 loc) · 2.42 KB
/
Copy pathclient-callback.rs
File metadata and controls
85 lines (72 loc) · 2.42 KB
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
//! Run with
//!
//! ```not_rust
//! cargo run --example client-callback
//! ```
//!
//! Run this example with the `server-callback` example.
use std::time::Duration;
use embedded_io_adapters::tokio_1::FromTokio;
use httparse::Header;
use rand::{
SeedableRng,
rngs::{StdRng, SysRng},
};
use tokio::net::TcpStream;
use websocketz::{Message, WebSocket, http::Response, next, options::ConnectOptions};
#[derive(Debug, thiserror::Error)]
#[error("No `Server-Header: Server-Value` header in the response")]
struct CustomError {}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let stream = TcpStream::connect("127.0.0.1:9002").await?;
let read_buf = &mut [0u8; 8192];
let write_buf = &mut [0u8; 8192];
let fragments_buf = &mut [0u8; 8192];
let rng = StdRng::try_from_rng(&mut SysRng).unwrap();
let (mut websocketz, custom) = WebSocket::connect_with(
ConnectOptions::default()
// Additional request headers
.with_headers(&[Header {
name: "Client-Header",
value: b"Client-Value",
}]),
FromTokio::new(stream),
rng,
read_buf,
write_buf,
fragments_buf,
|response: &Response<'_, 16>| {
// Fail the handshake if `Server-Header: Server-Value` header does not exist in the server response.
response
.headers()
.iter()
.find(|h| h.name.eq_ignore_ascii_case("Server-Header"))
.and_then(|h| core::str::from_utf8(h.value).ok())
.filter(|v| v.eq_ignore_ascii_case("Server-Value"))
.map(|_| ())
.ok_or(CustomError {})?;
// Create a custom value, depending on the response.
Ok::<&'static str, CustomError>("Ok!")
},
)
.await?;
println!("Extracted: {custom}");
println!(
"Number of framable bytes after handshake: {}",
websocketz.framable()
);
loop {
tokio::select! {
_ = tokio::time::sleep(Duration::from_secs(1)) => {
websocketz.send(Message::Text("Hi")).await?;
},
_ = async {
while let Some(message) = next!(websocketz).transpose()? {
println!("Received message: {message:?}");
}
Ok::<(), Box<dyn std::error::Error>>(())
} => {}
}
}
}