Open
Description
Bug Report
The client side code below, running in google chrome, will never call the Err(e) condition of write.send when the WS is disconnected from the webserver.
log::info!("Sent ping"); will appear with a error message i think originates from the webbrowser's websocket implementation:
Version
- cargo 1.85.0 (d73d2caf9 2024-12-31)
- wasm-pack --version wasm-pack 0.13.1
- chrome Version 133.0.6943.127 (Offizieller Build) (64-Bit)
Platform
wasm32-unknown-unknown
build with:
wasm-pack build --target web --release
It requires a webserver websocket which it can connect to. I'm using axum 0.7.9 on the server, see:
Crates
[package]
name = "pankat-wasm"
version = "0.1.0"
edition = "2021"
[dependencies]
serde = "1.0"
reqwest = { version = "0.11", features = ["json"] }
web-sys = { version = "0.3", features = ["WebSocket", "console", "MessageEvent", "Window", "Location", "Element", "DomTokenList", "CssStyleDeclaration"] }
wasm-bindgen = "0.2.100"
log = "0.4.25"
futures = "*"
wasm-bindgen-futures = "0.4.50"
console_log = "1.0.0"
gloo-net = { version = "0.5.0", default-features = false, features = ["websocket"] }
gloo-utils = { version = "0.2.0", default-features = false }
gloo-timers = { version = "0.3.0", features = ["futures"] }
anyhow = "1.0.95"
[lib]
crate-type = ["cdylib", "rlib"]
Description
1 use futures::StreamExt;
2 use gloo_net::websocket::{futures::WebSocket, Message};
3 use gloo_utils::window;
4 use std::{cell::RefCell, rc::Rc};
5 use wasm_bindgen::prelude::*;
6 use wasm_bindgen_futures::spawn_local;
7 use web_sys::{Element, HtmlElement};
8
9 #[wasm_bindgen(start)]
10 pub fn main_js() -> Result<(), JsValue> {
11 console_log::init_with_level(log::Level::Info).expect("error initializing log");
12 log::info!("Now executing WASM code from lib.rs in pankat_wasm");
13
14 spawn_local({
15 async move {
16 loop {
17 let location = window().location();
18 let protocol = if location.protocol().unwrap() == "https:" {
19 "wss"
20 } else {
21 "ws"
22 };
23
24 let host = location.host().unwrap();
25 let websocket_address = format!("{protocol}://{host}/api/ws");
26
27 match WebSocket::open(&websocket_address) {
28 Ok(ws) => {
29 let (mut write, mut read) = ws.split();
30 use futures::SinkExt;
31 spawn_local(async move {
32 loop {
33 gloo_timers::future::sleep(std::time::Duration::from_secs(1)).await;
34 match write.send(Message::Text("ping".to_string())).await {
35 Ok(_) => {
36 log::info!("Sent ping");
37 }
38 Err(e) => {
39 // BUG code never reached when WS goes down
40 log::warn!("Failed to send ping");
41 return;
42 }
43 }
44 }
45 });
46 while let Some(result) = read.next().await {
47 match result {
48 Ok(msg) => match msg {
49 Message::Text(message) => match message.as_str() {
50 "pong" => {
51 log::info!("WS: received a pong to our ping, connection is working!");
52 }
53 _ => {
54 log::info!("Received WS message");
55 }
56 },
57 Message::Bytes(_) => {
58 log::warn!("Binary messages are not supported yet");
59 }
60 },
61 Err(e) => {
62 log::warn!("Err0r {e}");
63 return;
64 }
65 }
66 }
67 log::info!(
68 "WebSocket disconnected, attempting to reconnect in 1 second..."
69 );
70 }
71 Err(e) => {
72 log::error!("Failed to connect: {}", e);
73 }
74 }
75 gloo_timers::future::sleep(std::time::Duration::from_secs(1)).await;
76 }
77 }
78 });
79
80 Ok(())
81 }