feat(liveview): add rocket adapter (#1761)

This commit is contained in:
Georges KABBOUCHI 2023-12-30 21:49:32 +02:00 committed by GitHub
parent 451d935aa2
commit 3733fbf47d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 119 additions and 1 deletions

View file

@ -38,6 +38,10 @@ salvo = { version = "0.44.1", optional = true, features = ["ws"] }
once_cell = "1.17.1"
async-trait = "0.1.71"
# rocket
rocket = { version = "0.5.0", optional = true }
rocket_ws = { version = "0.1.0", optional = true }
# actix is ... complicated?
# actix-files = { version = "0.6.2", optional = true }
# actix-web = { version = "4.2.1", optional = true }
@ -49,13 +53,16 @@ tokio = { workspace = true, features = ["full"] }
dioxus = { workspace = true }
warp = "0.3.3"
axum = { version = "0.6.1", features = ["ws"] }
salvo = { version = "0.44.1", features = ["affix", "ws"] }
# salvo = { version = "0.44.1", features = ["affix", "ws"] }
rocket = "0.5.0"
rocket_ws = "0.1.0"
tower = "0.4.13"
[features]
default = ["hot-reload"]
# actix = ["actix-files", "actix-web", "actix-ws"]
hot-reload = ["dioxus-hot-reload"]
rocket = ["dep:rocket", "dep:rocket_ws"]
[[example]]
name = "axum"
@ -68,3 +75,7 @@ required-features = ["salvo"]
[[example]]
name = "warp"
required-features = ["warp"]
[[example]]
name = "rocket"
required-features = ["rocket"]

View file

@ -28,6 +28,7 @@ The current backend frameworks supported include:
- Axum
- Warp
- Salvo
- Rocket
Dioxus-LiveView exports some primitives to wire up an app into an existing backend framework.

View file

@ -0,0 +1,76 @@
#[macro_use]
extern crate rocket;
use dioxus::prelude::*;
use dioxus_liveview::LiveViewPool;
use rocket::response::content::RawHtml;
use rocket::{Config, Rocket, State};
use rocket_ws::{Channel, WebSocket};
fn app(cx: Scope) -> Element {
let mut num = use_state(cx, || 0);
cx.render(rsx! {
div {
"hello Rocket! {num}"
button { onclick: move |_| num += 1, "Increment" }
}
})
}
fn index_page_with_glue(glue: &str) -> RawHtml<String> {
RawHtml(format!(
r#"
<!DOCTYPE html>
<html>
<head> <title>Dioxus LiveView with Rocket</title> </head>
<body> <div id="main"></div> </body>
{glue}
</html>
"#,
glue = glue
))
}
#[get("/")]
async fn index(config: &Config) -> RawHtml<String> {
index_page_with_glue(&dioxus_liveview::interpreter_glue(&format!(
"ws://{addr}:{port}/ws",
addr = config.address,
port = config.port,
)))
}
#[get("/as-path")]
async fn as_path() -> RawHtml<String> {
index_page_with_glue(&dioxus_liveview::interpreter_glue("/ws"))
}
#[get("/ws")]
fn ws(ws: WebSocket, pool: &State<LiveViewPool>) -> Channel<'static> {
let pool = pool.inner().to_owned();
ws.channel(move |stream| {
Box::pin(async move {
let _ = pool
.launch(dioxus_liveview::rocket_socket(stream), app)
.await;
Ok(())
})
})
}
#[tokio::main]
async fn main() {
let view = dioxus_liveview::LiveViewPool::new();
Rocket::build()
.manage(view)
.mount("/", routes![index, as_path, ws])
.ignite()
.await
.expect("Failed to ignite rocket")
.launch()
.await
.expect("Failed to launch rocket");
}

View file

@ -0,0 +1,25 @@
use crate::{LiveViewError, LiveViewSocket};
use rocket::futures::{SinkExt, StreamExt};
use rocket_ws::{result::Error, stream::DuplexStream, Message};
/// Convert a rocket websocket into a LiveViewSocket
///
/// This is required to launch a LiveView app using the rocket web framework
pub fn rocket_socket(stream: DuplexStream) -> impl LiveViewSocket {
stream
.map(transform_rx)
.with(transform_tx)
.sink_map_err(|_| LiveViewError::SendingFailed)
}
fn transform_rx(message: Result<Message, Error>) -> Result<Vec<u8>, LiveViewError> {
message
.map_err(|_| LiveViewError::SendingFailed)?
.into_text()
.map(|s| s.into_bytes())
.map_err(|_| LiveViewError::SendingFailed)
}
async fn transform_tx(message: Vec<u8>) -> Result<Message, Error> {
Ok(Message::Text(String::from_utf8_lossy(&message).to_string()))
}

View file

@ -18,6 +18,11 @@ pub mod adapters {
#[cfg(feature = "salvo")]
pub use salvo_adapter::*;
#[cfg(feature = "rocket")]
pub mod rocket_adapter;
#[cfg(feature = "rocket")]
pub use rocket_adapter::*;
}
pub use adapters::*;