codify "platform" into resolution logic, server-fn/fullstack overhaul (#4596)
overhaul dioxus fullstack using a new implementation of server_fn This PR is a complete rewrite of dioxus fullstack designed to improve compatibility with axum and to fix a number of compilation errors based on feature flag unification plumbing through macros.
This commit is contained in:
1 parent
8421c3aef0
commit
f2b1c6d97f
424 files changed
+17284
-6624
No files matched your search
@@ -5,14 +5,13 @@
|
||||
// - Hydration
|
||||
|
||||
#![allow(non_snake_case)]
|
||||
use dioxus::fullstack::{codec::JsonEncoding, commit_initial_chunk, BoxedStream, Websocket};
|
||||
use dioxus::prelude::*;
|
||||
use futures::{channel::mpsc, SinkExt, StreamExt};
|
||||
use dioxus::fullstack::{commit_initial_chunk, Websocket};
|
||||
use dioxus::{fullstack::WebSocketOptions, prelude::*};
|
||||
|
||||
fn main() {
|
||||
dioxus::LaunchBuilder::new()
|
||||
.with_cfg(server_only! {
|
||||
dioxus::fullstack::ServeConfig::builder().enable_out_of_order_streaming()
|
||||
dioxus::server::ServeConfig::builder().enable_out_of_order_streaming()
|
||||
})
|
||||
.with_context(1234u32)
|
||||
.launch(app);
|
||||
@@ -23,7 +22,7 @@ fn app() -> Element {
|
||||
let mut text = use_signal(|| "...".to_string());
|
||||
|
||||
rsx! {
|
||||
document::Title { "hello axum! {count}" }
|
||||
Title { "hello axum! {count}" }
|
||||
h1 { "hello axum! {count}" }
|
||||
button { class: "increment-button", onclick: move |_| count += 1, "Increment" }
|
||||
button {
|
||||
@@ -75,12 +74,14 @@ fn DefaultServerFnCodec() -> Element {
|
||||
|
||||
#[cfg(feature = "server")]
|
||||
async fn assert_server_context_provided() {
|
||||
use dioxus::server::{extract, FromContext};
|
||||
let FromContext(i): FromContext<u32> = extract().await.unwrap();
|
||||
assert_eq!(i, 1234u32);
|
||||
// todo!("replace server context....")
|
||||
// use dioxus::server::{extract, FromContext};
|
||||
// let FromContext(i): FromContext<u32> = extract().await.unwrap();
|
||||
// assert_eq!(i, 1234u32);
|
||||
}
|
||||
|
||||
#[server(PostServerData)]
|
||||
// #[server(PostServerData)]
|
||||
#[server]
|
||||
async fn post_server_data(data: String) -> ServerFnResult {
|
||||
assert_server_context_provided().await;
|
||||
println!("Server received: {}", data);
|
||||
@@ -88,7 +89,8 @@ async fn post_server_data(data: String) -> ServerFnResult {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[server(GetServerData)]
|
||||
// #[server(GetServerData)]
|
||||
#[server]
|
||||
async fn get_server_data() -> ServerFnResult<String> {
|
||||
assert_server_context_provided().await;
|
||||
Ok("Hello from the server!".to_string())
|
||||
@@ -105,9 +107,10 @@ async fn get_server_data_empty_vec(empty_vec: Vec<String>) -> ServerFnResult<Vec
|
||||
|
||||
#[server]
|
||||
async fn server_error() -> ServerFnResult<String> {
|
||||
use dioxus_core::AnyhowContext;
|
||||
assert_server_context_provided().await;
|
||||
tokio::time::sleep(tokio::time::Duration::from_millis(1000)).await;
|
||||
Err(ServerFnError::new("the server threw an error!"))
|
||||
Err(None.context("Server error occurred")?)
|
||||
}
|
||||
|
||||
#[component]
|
||||
@@ -165,49 +168,50 @@ fn DocumentElements() -> Element {
|
||||
fn Assets() -> Element {
|
||||
#[used]
|
||||
static _ASSET: Asset = asset!("/assets/image.png");
|
||||
|
||||
#[used]
|
||||
static _OTHER_ASSET: Asset = asset!("/assets/nested");
|
||||
static _STATIC_NO_HASH: Asset = asset!(
|
||||
"/assets/image.png",
|
||||
AssetOptions::image().with_hash_suffix(false)
|
||||
);
|
||||
|
||||
#[used]
|
||||
static _UNHASHED_FOLDER: Asset = asset!(
|
||||
"/assets/nested/",
|
||||
AssetOptions::folder().with_hash_suffix(false)
|
||||
);
|
||||
|
||||
#[used]
|
||||
static _EMBEDDED_FOLDER: Asset = asset!("/assets/nested");
|
||||
|
||||
rsx! {
|
||||
img {
|
||||
src: asset!("/assets/image.png"),
|
||||
}
|
||||
img {
|
||||
src: "/assets/image.png",
|
||||
src: "{_EMBEDDED_FOLDER}/image.png",
|
||||
}
|
||||
img {
|
||||
src: "/assets/nested/image.png",
|
||||
src: "{_UNHASHED_FOLDER}/image.png",
|
||||
}
|
||||
img {
|
||||
src: "/assets/image.png",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[server(protocol = Websocket<JsonEncoding, JsonEncoding>)]
|
||||
async fn echo_ws(
|
||||
input: BoxedStream<String, ServerFnError>,
|
||||
) -> ServerFnResult<BoxedStream<String, ServerFnError>> {
|
||||
let mut input = input;
|
||||
|
||||
let (mut tx, rx) = mpsc::channel(1);
|
||||
|
||||
tokio::spawn(async move {
|
||||
while let Some(msg) = input.next().await {
|
||||
let _ = tx.send(msg.map(|msg| msg.to_ascii_uppercase())).await;
|
||||
}
|
||||
});
|
||||
|
||||
Ok(rx.into())
|
||||
}
|
||||
|
||||
/// This component tests websocket server functions
|
||||
#[component]
|
||||
fn WebSockets() -> Element {
|
||||
let mut received = use_signal(String::new);
|
||||
|
||||
use_future(move || async move {
|
||||
let (mut tx, rx) = mpsc::channel(1);
|
||||
let mut receiver = echo_ws(rx.into()).await.unwrap();
|
||||
tx.send(Ok("hello world".to_string())).await.unwrap();
|
||||
while let Some(Ok(msg)) = receiver.next().await {
|
||||
println!("Received: {}", msg);
|
||||
received.set(msg);
|
||||
let socket = echo_ws(WebSocketOptions::default()).await.unwrap();
|
||||
|
||||
socket.send("hello world".to_string()).await.unwrap();
|
||||
|
||||
while let Ok(msg) = socket.recv().await {
|
||||
received.write().push_str(&msg);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -218,3 +222,16 @@ fn WebSockets() -> Element {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[get("/api/echo_ws")]
|
||||
async fn echo_ws(options: WebSocketOptions) -> Result<Websocket> {
|
||||
info!("Upgrading to websocket");
|
||||
|
||||
Ok(options.on_upgrade(
|
||||
|mut tx: dioxus::fullstack::TypedWebsocket<String, String>| async move {
|
||||
while let Ok(msg) = tx.recv().await {
|
||||
let _ = tx.send(msg.to_ascii_uppercase()).await;
|
||||
}
|
||||
},
|
||||
))
|
||||
}
|
||||
Reference in new issue
Block a user