attempt to reconnect to server after sever disconnects in debug mode
This commit is contained in:
1 parent
35dcacb956
commit
970d993758
5 files changed
+122
-21
No files matched your search
@@ -9,6 +9,7 @@
|
||||
use dioxus::prelude::*;
|
||||
use dioxus_router::*;
|
||||
use dioxus_server::prelude::*;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
fn main() {
|
||||
#[cfg(feature = "web")]
|
||||
@@ -62,7 +63,7 @@ fn main() {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Props, PartialEq)]
|
||||
#[derive(Clone, Debug, Props, PartialEq, Serialize, Deserialize)]
|
||||
struct AppProps {
|
||||
route: Option<String>,
|
||||
}
|
||||
|
||||
@@ -267,6 +267,7 @@ where
|
||||
.collect::<Vec<_>>()
|
||||
.join("/");
|
||||
let route = format!("/{}", route);
|
||||
println!("Serving static asset at {}", route);
|
||||
if path.is_dir() {
|
||||
self = self.nest_service(&route, ServeDir::new(path));
|
||||
} else {
|
||||
@@ -275,20 +276,43 @@ where
|
||||
}
|
||||
|
||||
// Add server functions and render index.html
|
||||
self.connect_hot_reload()
|
||||
.register_server_fns(server_fn_route)
|
||||
.route(
|
||||
"/",
|
||||
get(render_handler).with_state((cfg, SSRState::default())),
|
||||
)
|
||||
self.route(
|
||||
"/",
|
||||
get(render_handler).with_state((cfg, SSRState::default())),
|
||||
)
|
||||
.connect_hot_reload()
|
||||
.register_server_fns(server_fn_route)
|
||||
}
|
||||
|
||||
fn connect_hot_reload(self) -> Self {
|
||||
#[cfg(all(debug_assertions, feature = "hot-reload", feature = "ssr"))]
|
||||
{
|
||||
self.route(
|
||||
"/_dioxus/hot_reload",
|
||||
get(hot_reload_handler).with_state(crate::hot_reload::HotReloadState::default()),
|
||||
self.nest(
|
||||
"/_dioxus",
|
||||
Router::new()
|
||||
.route(
|
||||
"/hot_reload",
|
||||
get(hot_reload_handler)
|
||||
.with_state(crate::hot_reload::HotReloadState::default()),
|
||||
)
|
||||
.route(
|
||||
"/disconnect",
|
||||
get(|ws: WebSocketUpgrade| async {
|
||||
ws.on_failed_upgrade(|error| {
|
||||
println!("failed to upgrade: {}", error);
|
||||
todo!()
|
||||
})
|
||||
.on_upgrade(|mut ws| async move {
|
||||
use axum::extract::ws::Message;
|
||||
let _ = ws.send(Message::Text("connected".into())).await;
|
||||
loop {
|
||||
if ws.recv().await.is_none() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
})
|
||||
}),
|
||||
),
|
||||
)
|
||||
}
|
||||
#[cfg(not(all(debug_assertions, feature = "hot-reload", feature = "ssr")))]
|
||||
@@ -302,6 +326,7 @@ async fn render_handler<P: Clone + serde::Serialize + Send + Sync + 'static>(
|
||||
State((cfg, ssr_state)): State<(ServeConfig<P>, SSRState)>,
|
||||
request: Request<Body>,
|
||||
) -> impl IntoResponse {
|
||||
println!("Rendering");
|
||||
let (parts, _) = request.into_parts();
|
||||
let parts: Arc<RequestParts> = Arc::new(parts.into());
|
||||
let server_context = DioxusServerContext::new(parts);
|
||||
|
||||
@@ -261,7 +261,14 @@ impl DioxusRouterExt for Router {
|
||||
}
|
||||
|
||||
fn connect_hot_reload(self) -> Self {
|
||||
self.push(Router::with_path("/_dioxus/hot_reload").get(HotReloadHandler::default()))
|
||||
let mut _dioxus_router = Router::with_path("_dioxus");
|
||||
_dioxus_router = _dioxus_router
|
||||
.push(Router::with_path("hot_reload").handle(HotReloadHandler::default()));
|
||||
#[cfg(all(debug_assertions, feature = "hot-reload", feature = "ssr"))]
|
||||
{
|
||||
_dioxus_router = _dioxus_router.push(Router::with_path("disconnect").handle(ignore_ws));
|
||||
}
|
||||
self.push(_dioxus_router)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -504,3 +511,19 @@ impl HotReloadHandler {
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(all(debug_assertions, feature = "hot-reload", feature = "ssr"))]
|
||||
#[handler]
|
||||
async fn ignore_ws(req: &mut Request, res: &mut Response) -> Result<(), salvo::http::StatusError> {
|
||||
use salvo::ws::WebSocketUpgrade;
|
||||
WebSocketUpgrade::new()
|
||||
.upgrade(req, res, |mut ws| async move {
|
||||
let _ = dbg!(ws.send(salvo::ws::Message::text("connected")).await);
|
||||
while let Some(msg) = ws.recv().await {
|
||||
if msg.is_err() {
|
||||
return;
|
||||
};
|
||||
}
|
||||
})
|
||||
.await
|
||||
}
|
||||
@@ -360,7 +360,7 @@ pub fn connect_hot_reload() -> impl Filter<Extract = (impl Reply,), Error = warp
|
||||
{
|
||||
#[cfg(not(all(debug_assertions, feature = "hot-reload", feature = "ssr")))]
|
||||
{
|
||||
warp::path("_dioxus/hot_reload")
|
||||
warp::path!("_dioxus" / "hot_reload")
|
||||
.and(warp::ws())
|
||||
.map(warp::reply)
|
||||
.map(|reply| warp::reply::with_status(reply, warp::http::StatusCode::NOT_FOUND));
|
||||
@@ -368,20 +368,19 @@ pub fn connect_hot_reload() -> impl Filter<Extract = (impl Reply,), Error = warp
|
||||
#[cfg(all(debug_assertions, feature = "hot-reload", feature = "ssr"))]
|
||||
{
|
||||
use crate::hot_reload::HotReloadState;
|
||||
use futures_util::sink::SinkExt;
|
||||
use futures_util::StreamExt;
|
||||
use warp::ws::Message;
|
||||
|
||||
let state = HotReloadState::default();
|
||||
|
||||
warp::path("_dioxus")
|
||||
.and(warp::path("hot_reload"))
|
||||
warp::path!("_dioxus" / "hot_reload")
|
||||
.and(warp::ws())
|
||||
.and(warp::any().map(move || state.clone()))
|
||||
.map(move |ws: warp::ws::Ws, state: HotReloadState| {
|
||||
#[cfg(all(debug_assertions, feature = "hot-reload", feature = "ssr"))]
|
||||
ws.on_upgrade(move |mut websocket| {
|
||||
async move {
|
||||
use futures_util::sink::SinkExt;
|
||||
use futures_util::StreamExt;
|
||||
use warp::ws::Message;
|
||||
|
||||
println!("🔥 Hot Reload WebSocket connected");
|
||||
{
|
||||
// update any rsx calls that changed before the websocket connected.
|
||||
@@ -418,5 +417,25 @@ pub fn connect_hot_reload() -> impl Filter<Extract = (impl Reply,), Error = warp
|
||||
}
|
||||
})
|
||||
})
|
||||
.or(warp::path!("_dioxus" / "disconnect").and(warp::ws()).map(
|
||||
move |ws: warp::ws::Ws| {
|
||||
#[cfg(all(debug_assertions, feature = "hot-reload", feature = "ssr"))]
|
||||
ws.on_upgrade(move |mut websocket| async move {
|
||||
struct DisconnectOnDrop(Option<warp::ws::WebSocket>);
|
||||
impl Drop for DisconnectOnDrop {
|
||||
fn drop(&mut self) {
|
||||
let _ = self.0.take().unwrap().close();
|
||||
}
|
||||
}
|
||||
|
||||
let _ = websocket.send(Message::text("connected")).await;
|
||||
let mut ws = DisconnectOnDrop(Some(websocket));
|
||||
|
||||
loop {
|
||||
ws.0.as_mut().unwrap().next().await;
|
||||
}
|
||||
})
|
||||
},
|
||||
))
|
||||
}
|
||||
}
|
||||
@@ -25,9 +25,7 @@ impl Default for SSRState {
|
||||
impl SSRState {
|
||||
/// Render the application to HTML.
|
||||
pub fn render<P: 'static + Clone + serde::Serialize>(&self, cfg: &ServeConfig<P>) -> String {
|
||||
let ServeConfig {
|
||||
app, props, ..
|
||||
} = cfg;
|
||||
let ServeConfig { app, props, .. } = cfg;
|
||||
|
||||
let mut vdom = VirtualDom::new_with_props(*app, props.clone());
|
||||
|
||||
@@ -55,6 +53,41 @@ impl SSRState {
|
||||
// serialize the props
|
||||
let _ = crate::props_html::serialize_props::encode_in_element(&cfg.props, &mut html);
|
||||
|
||||
#[cfg(all(debug_assertions, feature = "hot-reload"))]
|
||||
{
|
||||
let disconnect_js = r#"(function () {
|
||||
const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
|
||||
const url = protocol + '//' + window.location.host + '/_dioxus/disconnect';
|
||||
const poll_interval = 1000;
|
||||
const reload_upon_connect = () => {
|
||||
console.log('Disconnected from server. Attempting to reconnect...');
|
||||
window.setTimeout(
|
||||
() => {
|
||||
// Try to reconnect to the websocket
|
||||
const ws = new WebSocket(url);
|
||||
ws.onopen = () => {
|
||||
// If we reconnect, reload the page
|
||||
window.location.reload();
|
||||
}
|
||||
// Otherwise, try again in a second
|
||||
reload_upon_connect();
|
||||
},
|
||||
poll_interval);
|
||||
};
|
||||
|
||||
// on initial page load connect to the disconnect ws
|
||||
const ws = new WebSocket(url);
|
||||
ws.onopen = () => {
|
||||
// if we disconnect, start polling
|
||||
ws.onclose = reload_upon_connect;
|
||||
};
|
||||
})()"#;
|
||||
|
||||
html += r#"<script>"#;
|
||||
html += disconnect_js;
|
||||
html += r#"</script>"#;
|
||||
}
|
||||
|
||||
html += &index.post_main;
|
||||
|
||||
html
|
||||
|
||||
Reference in new issue
Block a user