Upgrade to axum 0.7, drop 3rd party adapters

This commit is contained in:
Jonathan Kelley committed 2024-02-15 18:05:30 -08:00
1 parent 5dd33c9dcd
commit 214a907adc
53 files changed
+643 -3260

No files matched your search

@@ -81,10 +81,8 @@ impl LiveviewRouter for Router {
}
async fn start(self, address: impl Into<std::net::SocketAddr>) {
if let Err(err) = axum::Server::bind(&address.into())
.serve(self.into_make_service())
.await
{
let listener = tokio::net::TcpListener::bind(address.into()).await.unwrap();
if let Err(err) = axum::serve(listener, self.into_make_service()).await {
eprintln!("Failed to start axum server: {}", err);
}
}
-15
View File
@@ -2,26 +2,11 @@ use std::future::Future;
use dioxus_core::{Element, VirtualDom};
#[cfg(feature = "warp")]
pub mod warp_adapter;
#[cfg(feature = "warp")]
pub use warp_adapter::*;
#[cfg(feature = "axum")]
pub mod axum_adapter;
#[cfg(feature = "axum")]
pub use axum_adapter::*;
#[cfg(feature = "salvo")]
pub mod salvo_adapter;
#[cfg(feature = "salvo")]
pub use salvo_adapter::*;
#[cfg(feature = "rocket")]
pub mod rocket_adapter;
#[cfg(feature = "rocket")]
pub use rocket_adapter::*;
/// A trait for servers that can be used to host a LiveView app.
pub trait LiveviewRouter {
/// Create a new router.
@@ -1,113 +0,0 @@
use crate::LiveViewPool;
use crate::LiveviewRouter;
use crate::{LiveViewError, LiveViewSocket};
use rocket::futures::{SinkExt, StreamExt};
use rocket::response::content::RawHtml;
use rocket::{get, routes, State};
use rocket_ws::Channel;
use rocket_ws::WebSocket;
use rocket_ws::{result::Error, stream::DuplexStream, Message};
use std::sync::Arc;
/// 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::Binary(message))
}
impl LiveviewRouter for rocket::Rocket<rocket::Build> {
fn create_default_liveview_router() -> Self {
Self::build()
}
fn with_virtual_dom(
self,
route: &str,
app: impl Fn() -> dioxus_core::prelude::VirtualDom + Send + Sync + 'static,
) -> Self {
#[get("/")]
async fn index(request: &rocket::route::Route) -> RawHtml<String> {
let route = request.uri.base();
let glue = crate::interpreter_glue(&format!("{route}/ws",));
let title = crate::app_title();
RawHtml(format!(
r#"
<!DOCTYPE html>
<html>
<head> <title>{title}</title> </head>
<body> <div id="main"></div> </body>
{glue}
</html>
"#
))
}
#[get("/ws")]
fn ws(ws: WebSocket, app: &State<LiveviewApp>) -> Channel<'static> {
let app = app.inner();
let pool = app.pool.clone();
let app = app.app.clone();
ws.channel(move |stream| {
Box::pin(async move {
let _ = pool
.launch_virtualdom(crate::rocket_socket(stream), move || app())
.await;
Ok(())
})
})
}
struct LiveviewApp {
app: Arc<dyn Fn() -> dioxus_core::prelude::VirtualDom + Send + Sync + 'static>,
pool: LiveViewPool,
}
let app = Arc::new(app);
let view = crate::LiveViewPool::new();
self.manage(LiveviewApp {
app: app,
pool: view,
})
.mount(route, routes![index, ws])
}
async fn start(self, address: impl Into<std::net::SocketAddr>) {
let address = address.into();
let figment = self
.figment()
.clone()
.merge((rocket::Config::PORT, address.port()))
.merge((rocket::Config::ADDRESS, address.ip()));
self.configure(figment)
.ignite()
.await
.expect("Failed to ignite rocket")
.launch()
.await
.expect("Failed to launch rocket");
}
}
@@ -1,108 +0,0 @@
use crate::LiveViewPool;
use crate::LiveviewRouter;
use crate::{LiveViewError, LiveViewSocket};
use futures_util::{SinkExt, StreamExt};
use salvo::conn::TcpListener;
use salvo::http::StatusError;
use salvo::websocket::WebSocketUpgrade;
use salvo::websocket::{Message, WebSocket};
use salvo::writing::Text;
use salvo::Listener;
use salvo::Server;
use salvo::{handler, Depot, Request, Response, Router};
use std::sync::Arc;
/// Convert a Salvo WebSocket into a `LiveViewSocket`.
///
/// This is required to launch a LiveView app using the Salvo web framework.
pub fn salvo_socket(ws: WebSocket) -> impl LiveViewSocket {
ws.map(transform_rx)
.with(transform_tx)
.sink_map_err(|_| LiveViewError::SendingFailed)
}
fn transform_rx(message: Result<Message, salvo::Error>) -> Result<Vec<u8>, LiveViewError> {
let as_bytes = message.map_err(|_| LiveViewError::SendingFailed)?;
Ok(as_bytes.into())
}
async fn transform_tx(message: Vec<u8>) -> Result<Message, salvo::Error> {
Ok(Message::binary(message))
}
#[derive(Clone)]
struct LiveviewApp {
app: Arc<dyn Fn() -> dioxus_core::prelude::VirtualDom + Send + Sync + 'static>,
pool: Arc<LiveViewPool>,
}
impl LiveviewRouter for Router {
fn create_default_liveview_router() -> Self {
Self::new()
}
fn with_virtual_dom(
self,
route: &str,
app: impl Fn() -> dioxus_core::prelude::VirtualDom + Send + Sync + 'static,
) -> Self {
let app = Arc::new(app);
let view = crate::LiveViewPool::new();
self.push(
Router::with_path(route)
.hoop(salvo::affix::inject(LiveviewApp {
app: app,
pool: Arc::new(view),
}))
.get(index)
.push(Router::with_path("ws").get(connect)),
)
}
async fn start(self, address: impl Into<std::net::SocketAddr>) {
let address = address.into();
let acceptor = TcpListener::new(address).bind().await;
Server::new(acceptor).serve(self).await;
}
}
#[handler]
fn index(req: &mut Request, res: &mut Response) {
let base = req.uri().path();
let title = crate::app_title();
res.render(Text::Html(format!(
r#"
<!DOCTYPE html>
<html>
<head> <title>{title}</title> </head>
<body> <div id="main"></div> </body>
{glue}
</html>
"#,
glue = crate::interpreter_glue(&format!("{base}/ws"))
)));
}
#[handler]
async fn connect(
req: &mut Request,
depot: &mut Depot,
res: &mut Response,
) -> Result<(), StatusError> {
let app = depot.obtain::<LiveviewApp>().unwrap().clone();
let view = app.pool.clone();
let app = app.app.clone();
WebSocketUpgrade::new()
.upgrade(req, res, |ws| async move {
_ = view
.launch_virtualdom(crate::salvo_socket(ws), move || app())
.await;
})
.await
}
@@ -1,25 +0,0 @@
use crate::{LiveViewError, LiveViewSocket};
use futures_util::{SinkExt, StreamExt};
use warp::ws::{Message, WebSocket};
/// Convert a warp WebSocket into a `LiveViewSocket`.
///
/// This is required to launch a LiveView app using the warp web framework.
pub fn warp_socket(ws: WebSocket) -> impl LiveViewSocket {
ws.map(transform_rx)
.with(transform_tx)
.sink_map_err(|_| LiveViewError::SendingFailed)
}
fn transform_rx(message: Result<Message, warp::Error>) -> Result<Vec<u8>, LiveViewError> {
// Destructure the `message` into the buffer we got from warp.
let msg = message
.map_err(|_| LiveViewError::SendingFailed)?
.into_bytes();
Ok(msg)
}
async fn transform_tx(message: Vec<u8>) -> Result<Message, warp::Error> {
Ok(Message::binary(message))
}
-4
View File
@@ -3,10 +3,6 @@ use std::any::Any;
#[cfg(feature = "axum")]
pub type Config = crate::Config<axum::Router>;
#[cfg(all(feature = "salvo", not(feature = "axum")))]
pub type Config = crate::Config<salvo::Router>;
#[cfg(all(feature = "rocket", not(any(feature = "axum", feature = "salvo"))))]
pub type Config = crate::Config<rocket::Rocket<rocket::Build>>;
/// Launches the WebView and runs the event loop, with configuration and root props.
pub fn launch(
+3 -3
View File
@@ -25,7 +25,7 @@ impl<T> WebsocketRx for T where T: StreamExt<Item = Result<String, LiveViewError
#[derive(Debug, thiserror::Error)]
pub enum LiveViewError {
#[error("warp error")]
#[error("Sending to client error")]
SendingFailed,
}
@@ -113,7 +113,7 @@ pub fn interpreter_glue(url_or_path: &str) -> String {
// If the url starts with a `/`, generate glue which reuses current host
let get_ws_url = if url_or_path.starts_with('/') {
r#"
let loc = window.location;
let loc = window.location;
let new_url = "";
if (loc.protocol === "https:") {{
new_url = "wss:";
@@ -135,7 +135,7 @@ pub fn interpreter_glue(url_or_path: &str) -> String {
function __dioxusGetWsUrl(path) {{
{get_ws_url}
}}
var WS_ADDR = __dioxusGetWsUrl("{url_or_path}");
{handle_edits}
</script>