Skip to main content

print_frames/
print_frames.rs

1//! Prints the JSON of every WebSocket frame and a few HTTP bodies, as they go over the wire.
2//!
3//! ```text
4//! cargo run -p net_backend_protocol --example print_frames
5//! ```
6
7use net_backend_protocol::auth::{Account, AuthSession, LoginRequest, TokenPair};
8use net_backend_protocol::chat::{ChatMessage, JoinRoom, RoomInfo, RoomKind, SendAck, SendMessage};
9use net_backend_protocol::storage::{ObjectVersion, PutObject};
10use net_backend_protocol::{
11    codes, AccessToken, ApiError, CloseCode, ErrorBody, MessageId, RefreshToken, RoomId, UnixMillis, UserId, WsAuth, WsAuthOk, WsPushFrame, WsRequestFrame,
12    WsResponseFrame, WsServerFrame,
13};
14use serde::Serialize;
15
16fn show(label: &str, value: &impl Serialize) {
17    match serde_json::to_string(value) {
18        Ok(json) => println!("{label:<22} {json}"),
19        Err(error) => println!("{label:<22} <not serializable: {error}>"),
20    }
21}
22
23fn main() {
24    let now = UnixMillis(1_790_000_000_000);
25    println!("WebSocket");
26    println!("{:<22} {}", "auth (client)", WsAuth::new("example-access-token").to_message());
27    show("auth.ok", &WsServerFrame::AuthOk(Some(WsAuthOk::new(UserId(42)))));
28    show("auth.failed", &WsServerFrame::AuthFailed(ApiError::new(codes::TOKEN_EXPIRED, "the token expired")));
29    show("request chat.join", &WsRequestFrame::call(1, JoinRoom::new("world")));
30    show("answer", &WsResponseFrame::ok(1, RoomInfo::new(RoomId(12), RoomKind::Room).with_key("world")));
31    show("request chat.send", &WsRequestFrame::call(2, SendMessage::new(RoomId(12), "hello")));
32    show("answer", &WsResponseFrame::ok(2, SendAck::new(MessageId(981), now)));
33    show("refused", &WsResponseFrame::<()>::error(3, ApiError::new(codes::NOT_A_MEMBER, "join the room first")));
34    show("push chat.message", &WsPushFrame::push(ChatMessage::new(MessageId(981), RoomId(12), UserId(42), "hello", now).with_sender_name("Ada")));
35    let codes: Vec<String> = CloseCode::ALL.iter().map(|c| format!("{c}{}", if c.is_permanent() { " (permanent)" } else { "" })).collect();
36    println!("{:<22} {}", "close codes", codes.join(", "));
37
38    println!();
39    println!("HTTP");
40    show("POST login", &LoginRequest::new("ada@example.com", "example password"));
41    let tokens = TokenPair::new(
42        AccessToken::new("example-access"),
43        now.saturating_add_millis(3_600_000),
44        RefreshToken::new("example-refresh"),
45        now.saturating_add_millis(30 * 86_400_000),
46    );
47    show("  → 200", &AuthSession::new(Account::new(UserId(42), now).with_email("ada@example.com", true), tokens));
48    show("PUT storage object", &PutObject::new(serde_json::json!({"level": 3})).if_version(ObjectVersion(2)));
49    show("  → 409", &ErrorBody::new(ApiError::new(codes::VERSION_CONFLICT, "the object changed").with_details(serde_json::json!({"current_version": 3}))));
50}