Send data to the server and stop the time [wip]

TODO:
- Get rid of the unwraps
- Try to get rid of SpaRouter
This commit is contained in:
finga 2022-09-18 23:50:06 +02:00 committed by Fabian Nedoluha
parent b12b8765a9
commit 8f695e5dd7
No known key found for this signature in database
GPG key ID: 55526D82CD852914
6 changed files with 517 additions and 4 deletions

376
Cargo.lock generated
View file

@ -88,9 +88,11 @@ checksum = "c9e3356844c4d6a6d6467b8da2cffb4a2820be256f50a3a386c9d152bab31043"
dependencies = [
"async-trait",
"axum-core",
"base64",
"bitflags",
"bytes",
"futures-util",
"headers",
"http",
"http-body",
"hyper",
@ -103,8 +105,10 @@ dependencies = [
"serde",
"serde_json",
"serde_urlencoded",
"sha-1",
"sync_wrapper",
"tokio",
"tokio-tungstenite",
"tower",
"tower-http",
"tower-layer",
@ -152,12 +156,30 @@ version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd"
[[package]]
name = "bincode"
version = "1.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad"
dependencies = [
"serde",
]
[[package]]
name = "bitflags"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "block-buffer"
version = "0.10.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "69cce20737498f97b993470a6e536b8523f0af7892a4f928cceb1ac5e52ebe7e"
dependencies = [
"generic-array",
]
[[package]]
name = "boolinator"
version = "2.4.0"
@ -191,6 +213,12 @@ version = "3.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c1ad822118d20d2c234f427000d5acc36eabe1e29a348c89b63dd60b13f28e5d"
[[package]]
name = "byteorder"
version = "1.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
[[package]]
name = "bytes"
version = "1.2.1"
@ -246,12 +274,18 @@ dependencies = [
name = "client"
version = "0.1.0"
dependencies = [
"bincode",
"console_error_panic_hook",
"futures",
"gloo-net",
"gloo-timers",
"instant",
"log",
"serde",
"wasm-bindgen-futures",
"wasm-logger",
"yew",
"yew-router",
]
[[package]]
@ -264,6 +298,15 @@ dependencies = [
"wasm-bindgen",
]
[[package]]
name = "cpufeatures"
version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "28d997bd5e24a5928dd43e46dc529867e207907fe0b239c3477d924f7f2ca320"
dependencies = [
"libc",
]
[[package]]
name = "crc32fast"
version = "1.3.2"
@ -273,6 +316,26 @@ dependencies = [
"cfg-if",
]
[[package]]
name = "crypto-common"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
dependencies = [
"generic-array",
"typenum",
]
[[package]]
name = "digest"
version = "0.10.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "adfbc57365a37acbd2ebf2b64d7e69bb766e2fea813521ed536f5d0520dcf86c"
dependencies = [
"block-buffer",
"crypto-common",
]
[[package]]
name = "flate2"
version = "1.0.24"
@ -298,6 +361,21 @@ dependencies = [
"percent-encoding",
]
[[package]]
name = "futures"
version = "0.3.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f21eda599937fba36daeb58a22e8f5cee2d14c4a17b5b7739c7c8e5e3b8230c"
dependencies = [
"futures-channel",
"futures-core",
"futures-executor",
"futures-io",
"futures-sink",
"futures-task",
"futures-util",
]
[[package]]
name = "futures-channel"
version = "0.3.24"
@ -305,6 +383,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "30bdd20c28fadd505d0fd6712cdfcb0d4b5648baf45faef7f852afb2399bb050"
dependencies = [
"futures-core",
"futures-sink",
]
[[package]]
@ -313,6 +392,34 @@ version = "0.3.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4e5aa3de05362c3fb88de6531e6296e85cde7739cccad4b9dfeeb7f6ebce56bf"
[[package]]
name = "futures-executor"
version = "0.3.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ff63c23854bee61b6e9cd331d523909f238fc7636290b96826e9cfa5faa00ab"
dependencies = [
"futures-core",
"futures-task",
"futures-util",
]
[[package]]
name = "futures-io"
version = "0.3.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbf4d2a7a308fd4578637c0b17c7e1c7ba127b8f6ba00b29f717e9655d85eb68"
[[package]]
name = "futures-macro"
version = "0.3.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42cd15d1c7456c04dbdf7e88bcd69760d74f3a798d6444e16974b505b0e62f17"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "futures-sink"
version = "0.3.24"
@ -331,13 +438,28 @@ version = "0.3.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "44fb6cb1be61cc1d2e43b262516aafcf63b241cffdb1d3fa115f91d9c7b09c90"
dependencies = [
"futures-channel",
"futures-core",
"futures-io",
"futures-macro",
"futures-sink",
"futures-task",
"memchr",
"pin-project-lite",
"pin-utils",
"slab",
]
[[package]]
name = "generic-array"
version = "0.14.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9"
dependencies = [
"typenum",
"version_check",
]
[[package]]
name = "getrandom"
version = "0.2.7"
@ -404,12 +526,33 @@ version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a8d5564e570a38b43d78bdc063374a0c3098c4f0d64005b12f9bbe87e869b6d7"
dependencies = [
"futures-channel",
"gloo-events",
"js-sys",
"wasm-bindgen",
"web-sys",
]
[[package]]
name = "gloo-net"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec897194fb9ac576c708f63d35604bc58f2a262b8cec0fabfed26f3991255f21"
dependencies = [
"futures-channel",
"futures-core",
"futures-sink",
"gloo-utils",
"js-sys",
"pin-project",
"serde",
"serde_json",
"thiserror",
"wasm-bindgen",
"wasm-bindgen-futures",
"web-sys",
]
[[package]]
name = "gloo-render"
version = "0.1.1"
@ -441,6 +584,8 @@ version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5fb7d06c1c8cc2a29bee7ec961009a0b2caa0793ee4900c2ffb348734ba1c8f9"
dependencies = [
"futures-channel",
"futures-core",
"js-sys",
"wasm-bindgen",
]
@ -464,6 +609,31 @@ version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
[[package]]
name = "headers"
version = "0.3.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f3e372db8e5c0d213e0cd0b9be18be2aca3d44cf2fe30a9d46a65581cd454584"
dependencies = [
"base64",
"bitflags",
"bytes",
"headers-core",
"http",
"httpdate",
"mime",
"sha1",
]
[[package]]
name = "headers-core"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e7f66481bfee273957b1f20485a4ff3362987f85b2c236580d81b4eb7a326429"
dependencies = [
"http",
]
[[package]]
name = "heck"
version = "0.4.0"
@ -542,6 +712,16 @@ dependencies = [
"want",
]
[[package]]
name = "idna"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6"
dependencies = [
"unicode-bidi",
"unicode-normalization",
]
[[package]]
name = "indexmap"
version = "1.9.1"
@ -617,7 +797,10 @@ dependencies = [
"anyhow",
"axum",
"axum-extra",
"bincode",
"clap",
"client",
"headers",
"log",
"tokio",
"tower",
@ -782,6 +965,12 @@ version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
[[package]]
name = "ppv-lite86"
version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872"
[[package]]
name = "proc-macro-error"
version = "1.0.4"
@ -824,6 +1013,36 @@ dependencies = [
"proc-macro2",
]
[[package]]
name = "rand"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
dependencies = [
"libc",
"rand_chacha",
"rand_core",
]
[[package]]
name = "rand_chacha"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
dependencies = [
"ppv-lite86",
"rand_core",
]
[[package]]
name = "rand_core"
version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
dependencies = [
"getrandom",
]
[[package]]
name = "redox_syscall"
version = "0.2.16"
@ -833,6 +1052,12 @@ dependencies = [
"bitflags",
]
[[package]]
name = "route-recognizer"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "afab94fb28594581f62d981211a9a4d53cc8130bbcbbb89a0440d9b8e81a7746"
[[package]]
name = "ryu"
version = "1.0.11"
@ -860,6 +1085,18 @@ dependencies = [
"serde_derive",
]
[[package]]
name = "serde-wasm-bindgen"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "618365e8e586c22123d692b72a7d791d5ee697817b65a218cdf12a98870af0f7"
dependencies = [
"fnv",
"js-sys",
"serde",
"wasm-bindgen",
]
[[package]]
name = "serde_derive"
version = "1.0.144"
@ -894,6 +1131,28 @@ dependencies = [
"serde",
]
[[package]]
name = "sha-1"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "028f48d513f9678cda28f6e4064755b3fbb2af6acd672f2c209b62323f7aea0f"
dependencies = [
"cfg-if",
"cpufeatures",
"digest",
]
[[package]]
name = "sha1"
version = "0.10.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f04293dc80c3993519f2d7f6f511707ee7094fe0c6d3406feb330cdb3540eba3"
dependencies = [
"cfg-if",
"cpufeatures",
"digest",
]
[[package]]
name = "sharded-slab"
version = "0.1.4"
@ -1004,6 +1263,21 @@ dependencies = [
"once_cell",
]
[[package]]
name = "tinyvec"
version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50"
dependencies = [
"tinyvec_macros",
]
[[package]]
name = "tinyvec_macros"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c"
[[package]]
name = "tokio"
version = "1.21.1"
@ -1036,6 +1310,18 @@ dependencies = [
"syn",
]
[[package]]
name = "tokio-tungstenite"
version = "0.17.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f714dd15bead90401d77e04243611caec13726c2408afd5b31901dfcdcb3b181"
dependencies = [
"futures-util",
"log",
"tokio",
"tungstenite",
]
[[package]]
name = "tokio-util"
version = "0.7.4"
@ -1160,6 +1446,31 @@ version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642"
[[package]]
name = "tungstenite"
version = "0.17.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e27992fd6a8c29ee7eef28fc78349aa244134e10ad447ce3b9f0ac0ed0fa4ce0"
dependencies = [
"base64",
"byteorder",
"bytes",
"http",
"httparse",
"log",
"rand",
"sha-1",
"thiserror",
"url",
"utf-8",
]
[[package]]
name = "typenum"
version = "1.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987"
[[package]]
name = "unicase"
version = "2.6.0"
@ -1169,12 +1480,44 @@ dependencies = [
"version_check",
]
[[package]]
name = "unicode-bidi"
version = "0.3.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992"
[[package]]
name = "unicode-ident"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dcc811dc4066ac62f84f11307873c4850cb653bfa9b1719cee2bd2204a4bc5dd"
[[package]]
name = "unicode-normalization"
version = "0.1.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921"
dependencies = [
"tinyvec",
]
[[package]]
name = "url"
version = "2.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0d68c799ae75762b8c3fe375feb6600ef5602c883c5d21eb51c09f22b83c4643"
dependencies = [
"form_urlencoded",
"idna",
"percent-encoding",
]
[[package]]
name = "utf-8"
version = "0.7.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9"
[[package]]
name = "uuid"
version = "1.1.2"
@ -1219,6 +1562,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eaf9f5aceeec8be17c128b2e93e031fb8a4d469bb9c4ae2d7dc1888b26887268"
dependencies = [
"cfg-if",
"serde",
"serde_json",
"wasm-bindgen-macro",
]
@ -1405,3 +1750,34 @@ dependencies = [
"quote",
"syn",
]
[[package]]
name = "yew-router"
version = "0.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "155804f6f3aa309f596d5c3fa14486a94e7756f1edd7634569949e401d5099f2"
dependencies = [
"gloo",
"gloo-utils",
"js-sys",
"route-recognizer",
"serde",
"serde-wasm-bindgen",
"serde_urlencoded",
"thiserror",
"wasm-bindgen",
"web-sys",
"yew",
"yew-router-macro",
]
[[package]]
name = "yew-router-macro"
version = "0.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "39049d193b52eaad4ffc80916bf08806d142c90b5edcebd527644de438a7e19a"
dependencies = [
"proc-macro2",
"quote",
"syn",
]

View file

@ -14,5 +14,11 @@ yew = "0.19"
console_error_panic_hook = "0.1"
log = "0.4"
wasm-logger = "0.2"
futures = "0.3"
gloo-timers = "0.2"
gloo-net = "0.2"
instant = { version = "0.1", features = [ "wasm-bindgen" ] }
wasm-bindgen-futures = "0.4"
bincode = "1"
yew-router = "0.16"
serde = { version = "1", features = ["derive"] }

9
client/src/lib.rs Normal file
View file

@ -0,0 +1,9 @@
use serde::{Deserialize, Serialize};
use std::time::Duration;
#[derive(Debug, Deserialize, Serialize)]
pub enum Message {
Start,
Stop,
Duration(Duration),
}

View file

@ -1,6 +1,54 @@
use futures::{
stream::{SplitSink, SplitStream},
SinkExt, StreamExt,
};
use gloo_net::websocket::{futures::WebSocket, Message};
use gloo_timers::callback::Interval;
use instant::Instant;
use log::debug;
use std::sync::{Arc, Mutex};
use wasm_bindgen_futures::spawn_local;
use yew::prelude::*;
use yew_router::prelude::*;
#[derive(Routable, PartialEq, Clone, Debug)]
pub enum Route {
#[at("/")]
LockWatch,
#[not_found]
#[at("/404")]
NotFound,
}
struct WebSocketHandle {
writer: Arc<Mutex<SplitSink<WebSocket, Message>>>,
_reader: Arc<Mutex<SplitStream<WebSocket>>>,
}
impl WebSocketHandle {
fn connect() -> Self {
debug!("connect to websocket");
let ws = WebSocket::open("ws://localhost:3000/api/ws").unwrap();
let (writer, reader) = ws.split();
Self {
writer: Arc::new(Mutex::new(writer)),
_reader: Arc::new(Mutex::new(reader)),
}
}
fn send(&self, msg: client::Message) {
let writer = self.writer.clone();
spawn_local(async move {
writer
.lock()
.unwrap()
.send(Message::Bytes(bincode::serialize(&msg).unwrap()))
.await
.unwrap();
});
}
}
enum Msg {
Start,
@ -9,6 +57,7 @@ enum Msg {
}
struct LockWatch {
websocket: WebSocketHandle,
duration: Option<Instant>,
duration_handle: Option<Interval>,
}
@ -38,6 +87,7 @@ impl Component for LockWatch {
fn create(_ctx: &Context<Self>) -> Self {
Self {
websocket: WebSocketHandle::connect(),
duration: None,
duration_handle: None,
}
@ -47,6 +97,8 @@ impl Component for LockWatch {
match msg {
Msg::Start => {
self.duration = Some(Instant::now());
self.websocket.send(client::Message::Start);
self.duration_handle = {
let link = ctx.link().clone();
Some(Interval::new(1, move || {
@ -54,7 +106,12 @@ impl Component for LockWatch {
}))
};
}
Msg::Stop => self.duration_handle = None,
Msg::Stop => {
self.duration_handle = None;
self.websocket.send(client::Message::Stop);
let duration = self.duration.unwrap().elapsed();
self.websocket.send(client::Message::Duration(duration));
}
Msg::UpdateDuration => {}
}

View file

@ -12,10 +12,13 @@ categories = ["web-programming::http-server"]
[dependencies]
anyhow = "1"
log = "0.4"
axum = "0.5"
axum = { version = "0.5", features = ["ws", "headers"] }
axum-extra = { version = "0.3", features = ["spa"] }
tokio = { version = "1.0", features = ["full"] }
tracing-subscriber = "0.3"
tower = "0.4"
tower-http = { version = "0.3", features = ["full"] }
clap = { version = "3", features = ["derive"] }
headers = "0.3"
bincode = "1"
client = { path = "../client" }

View file

@ -1,11 +1,21 @@
use anyhow::Result;
use axum::Router;
use axum::{
extract::{
ws::{Message, WebSocket},
WebSocketUpgrade,
},
response::IntoResponse,
routing::get,
Router, TypedHeader,
};
use axum_extra::routing::SpaRouter;
use clap::{ArgAction, Parser};
use log::info;
use headers::UserAgent;
use log::{debug, info, trace, warn};
use std::{
env,
net::{IpAddr, SocketAddr},
time::Instant,
};
use tower::ServiceBuilder;
use tower_http::trace::TraceLayer;
@ -27,6 +37,57 @@ struct Cli {
verbosity: u8,
}
async fn handle_websocket(mut socket: WebSocket) {
let mut start: Option<Instant> = None;
loop {
if let Some(msg) = socket.recv().await {
if let Ok(msg) = msg {
match msg {
Message::Binary(b) => {
let message = bincode::deserialize::<client::Message>(&b).unwrap();
trace!("received message on websocket: {:?}", message);
match message {
client::Message::Start => start = Some(Instant::now()),
client::Message::Stop => {
info!("server measured {:?}", start.unwrap().elapsed())
}
client::Message::Duration(d) => info!("client measured {:?}", d),
}
}
Message::Ping(p) => {
debug!("websocket ping: {:?}", p);
}
Message::Pong(p) => {
debug!("websocket pong: {:?}", p);
}
Message::Close(m) => {
info!("client disconnected: {:?}", m);
return;
}
m => warn!("websocket message not implemented: {:?}", m),
}
} else {
info!("client disconnected");
return;
}
}
}
}
#[allow(clippy::unused_async)]
async fn websocket_handler(
ws: WebSocketUpgrade,
user_agent: Option<TypedHeader<UserAgent>>,
) -> impl IntoResponse {
if let Some(TypedHeader(user_agent)) = user_agent {
info!("`{}` connected", user_agent.as_str());
}
ws.on_upgrade(handle_websocket)
}
#[tokio::main]
async fn main() -> Result<()> {
let cli = Cli::parse();
@ -38,6 +99,7 @@ async fn main() -> Result<()> {
tracing_subscriber::fmt::init();
let app = Router::new()
.route("/api/ws", get(websocket_handler))
.merge(SpaRouter::new("/client", cli.static_dir))
.layer(ServiceBuilder::new().layer(TraceLayer::new_for_http()));