Fix websocket server functions and add an example (#4107)

* Fix websocket server function

* Add websocket test

* add a websocket example

* fix clippy
This commit is contained in:
Evan Almloff authored and GitHub committed 2025-05-14 08:28:43 +02:00
1 parent e47d0aa868
commit 6b70ba7cd2
10 files changed
+297 -12

No files matched your search

+4
View File
@@ -0,0 +1,4 @@
dist
target
static
.dioxus
+16
View File
@@ -0,0 +1,16 @@
[package]
name = "fullstack-websocket-example"
version = "0.1.0"
edition = "2021"
publish = false
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
dioxus = { workspace = true, features = ["fullstack"] }
futures.workspace = true
tokio = { workspace = true, features = ["full"], optional = true }
[features]
server = ["dioxus/server", "dep:tokio"]
web = ["dioxus/web"]
+69
View File
@@ -0,0 +1,69 @@
#![allow(non_snake_case)]
use dioxus::prelude::{
server_fn::{codec::JsonEncoding, BoxedStream, Websocket},
*,
};
use futures::{channel::mpsc, SinkExt, StreamExt};
fn main() {
launch(app);
}
fn app() -> Element {
let mut uppercase = use_signal(String::new);
let mut uppercase_channel = use_signal(|| None);
// Start the websocket connection in a background task
use_future(move || async move {
let (tx, rx) = mpsc::channel(1);
let mut receiver = uppercase_ws(rx.into()).await.unwrap();
// Store the channel in a signal for use in the input handler
uppercase_channel.set(Some(tx));
// Whenever we get a message from the server, update the uppercase signal
while let Some(Ok(msg)) = receiver.next().await {
uppercase.set(msg);
}
});
rsx! {
input {
oninput: move |e| async move {
if let Some(mut uppercase_channel) = uppercase_channel() {
let msg = e.value();
uppercase_channel.send(Ok(msg)).await.unwrap();
}
},
}
"Uppercase: {uppercase}"
}
}
// The server macro accepts a protocol parameter which implements the protocol trait. The protocol
// controls how the inputs and outputs are encoded when handling the server function. In this case,
// the websocket<json, json> protocol can encode a stream input and stream output where messages are
// serialized as JSON
#[server(protocol = Websocket<JsonEncoding, JsonEncoding>)]
async fn uppercase_ws(
input: BoxedStream<String, ServerFnError>,
) -> Result<BoxedStream<String, ServerFnError>, ServerFnError> {
let mut input = input;
// Create a channel with the output of the websocket
let (mut tx, rx) = mpsc::channel(1);
// Spawn a task that processes the input stream and sends any new messages to the output
tokio::spawn(async move {
while let Some(msg) = input.next().await {
if tx
.send(msg.map(|msg| msg.to_ascii_uppercase()))
.await
.is_err()
{
break;
}
}
});
// Return the output stream
Ok(rx.into())
}