use futures_util::StreamExt;
use serde::{Deserialize, Serialize};
use skyzen::{
routing::{CreateRouteNode, Route, Router},
websocket::{WebSocketMessage, WebSocketUpgrade},
Responder, Result,
};
#[derive(Serialize, Deserialize, Debug)]
struct ChatMessage {
user: String,
content: String,
}
async fn websocket_echo(upgrade: WebSocketUpgrade) -> impl Responder {
upgrade.on_upgrade(|mut socket| async move {
while let Some(message) = socket.next().await {
match message? {
WebSocketMessage::Text(text) => socket.send_text(format!("echo:{text}")).await?,
WebSocketMessage::Close => {
tracing::info!("client closed the text echo session");
break;
}
_ => {}
}
}
Ok::<_, skyzen::Error>(())
})
}
async fn websocket_json(upgrade: WebSocketUpgrade) -> impl Responder {
upgrade.on_upgrade(|mut socket| async move {
while let Some(message) = socket.recv_json::<ChatMessage>().await {
let message = message?;
tracing::info!(user = %message.user, content = %message.content, "received");
socket
.send(&ChatMessage {
user: "server".to_owned(),
content: format!("Echo: {}", message.content),
})
.await?;
}
tracing::info!("client closed the json session");
Ok::<_, skyzen::Error>(())
})
}
async fn websocket_binary(upgrade: WebSocketUpgrade) -> impl Responder {
upgrade.on_upgrade(|mut socket| async move {
while let Some(message) = socket.next().await {
if let Some(data) = message?.into_bytes() {
tracing::info!(bytes = data.len(), "received");
let mut response = vec![0xFF];
response.extend_from_slice(&data);
socket.send_binary(response).await?;
}
}
Ok::<_, skyzen::Error>(())
})
}
async fn shorthand_echo(mut socket: skyzen::websocket::WebSocket) -> Result<()> {
while let Some(message) = socket.next().await {
if let Some(text) = message?.into_text() {
socket.send_text(text).await?;
}
}
Ok(())
}
async fn health() -> &'static str {
"ok"
}
fn router() -> Router {
Route::new((
"/ws".at(websocket_echo),
"/ws/json".at(websocket_json),
"/ws/binary".at(websocket_binary),
"/ws/shorthand".ws(shorthand_echo),
"/health".at(health),
))
.build()
}
#[skyzen::main]
fn main() -> Router {
router()
}