fix other fullstack adapters
This commit is contained in:
1 parent
694bef0d93
commit
89b1e56fc3
9 files changed
+105
-95
No files matched your search
@@ -49,6 +49,7 @@
|
||||
//! }
|
||||
//! ```
|
||||
|
||||
use dioxus_lib::prelude::*;
|
||||
use http_body_util::{BodyExt, Limited};
|
||||
use hyper::body::Body as HyperBody;
|
||||
use hyper::StatusCode;
|
||||
@@ -201,10 +202,11 @@ pub trait DioxusRouterExt {
|
||||
///
|
||||
/// fn app() -> Element {todo!()}
|
||||
/// ```
|
||||
fn serve_dioxus_application<P: Clone + serde::Serialize + Send + Sync + 'static>(
|
||||
fn serve_dioxus_application(
|
||||
self,
|
||||
server_fn_path: &'static str,
|
||||
cfg: impl Into<ServeConfig<P>>,
|
||||
cfg: impl Into<ServeConfig>,
|
||||
virtual_dom_factory: impl Fn() -> VirtualDom + Send + Sync + 'static,
|
||||
) -> Self;
|
||||
}
|
||||
|
||||
@@ -281,10 +283,11 @@ impl DioxusRouterExt for Router {
|
||||
self
|
||||
}
|
||||
|
||||
fn serve_dioxus_application<P: Clone + serde::Serialize + Send + Sync + 'static>(
|
||||
fn serve_dioxus_application(
|
||||
self,
|
||||
server_fn_path: &'static str,
|
||||
cfg: impl Into<ServeConfig<P>>,
|
||||
cfg: impl Into<ServeConfig>,
|
||||
virtual_dom_factory: impl Fn() -> VirtualDom + Send + Sync + 'static,
|
||||
) -> Self {
|
||||
let cfg = cfg.into();
|
||||
|
||||
@@ -376,19 +379,26 @@ async fn convert_response(response: HyperResponse, res: &mut Response) {
|
||||
}
|
||||
|
||||
/// A handler that renders a Dioxus application to HTML using server-side rendering.
|
||||
pub struct SSRHandler<P: Clone> {
|
||||
cfg: ServeConfig<P>,
|
||||
pub struct SSRHandler {
|
||||
config: ServeConfig,
|
||||
virtual_dom: Box<dyn Fn() -> VirtualDom + Send + Sync>,
|
||||
}
|
||||
|
||||
impl<P: Clone> SSRHandler<P> {
|
||||
impl SSRHandler {
|
||||
/// Creates a new SSR handler with the given configuration.
|
||||
pub fn new(cfg: ServeConfig<P>) -> Self {
|
||||
Self { cfg }
|
||||
pub fn new(
|
||||
config: ServeConfig,
|
||||
virtual_dom: impl Fn() -> VirtualDom + Send + Sync + 'static,
|
||||
) -> Self {
|
||||
Self {
|
||||
config,
|
||||
virtual_dom: Box::new(virtual_dom),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl<P: Clone + serde::Serialize + Send + Sync + 'static> Handler for SSRHandler<P> {
|
||||
impl Handler for SSRHandler {
|
||||
async fn handle(
|
||||
&self,
|
||||
req: &mut Request,
|
||||
|
||||
@@ -52,6 +52,7 @@ use crate::{
|
||||
};
|
||||
|
||||
use crate::server_fn_service;
|
||||
use dioxus_lib::prelude::VirtualDom;
|
||||
use server_fn::{Encoding, Payload, ServerFunctionRegistry};
|
||||
use std::error::Error;
|
||||
use std::sync::Arc;
|
||||
@@ -179,68 +180,85 @@ pub fn register_server_fns(server_fn_route: &'static str) -> BoxedFilter<(impl R
|
||||
/// todo!()
|
||||
/// }
|
||||
/// ```
|
||||
pub fn serve_dioxus_application<P: Clone + serde::Serialize + Send + Sync + 'static>(
|
||||
pub fn serve_dioxus_application(
|
||||
server_fn_route: &'static str,
|
||||
cfg: impl Into<ServeConfig<P>>,
|
||||
cfg: impl Into<ServeConfig>,
|
||||
virtual_dom_factory: impl Fn() -> VirtualDom + Send + Sync + 'static,
|
||||
) -> BoxedFilter<(impl Reply,)> {
|
||||
let cfg = cfg.into();
|
||||
// Serve the dist folder and the index.html file
|
||||
let serve_dir = warp::fs::dir(cfg.assets_path);
|
||||
|
||||
let virtual_dom_factory =
|
||||
Arc::new(virtual_dom_factory) as Arc<dyn Fn() -> VirtualDom + Send + Sync + 'static>;
|
||||
|
||||
connect_hot_reload()
|
||||
// First register the server functions
|
||||
.or(register_server_fns(server_fn_route))
|
||||
// Then the index route
|
||||
.or(path::end().and(render_ssr(cfg.clone())))
|
||||
.or(path::end().and(render_ssr(cfg.clone(), {
|
||||
let virtual_dom_factory = virtual_dom_factory.clone();
|
||||
move || virtual_dom_factory()
|
||||
})))
|
||||
// Then the static assets
|
||||
.or(serve_dir)
|
||||
// Then all other routes
|
||||
.or(render_ssr(cfg))
|
||||
.or(render_ssr(cfg, move || virtual_dom_factory()))
|
||||
.boxed()
|
||||
}
|
||||
|
||||
/// Server render the application.
|
||||
pub fn render_ssr<P: Clone + serde::Serialize + Send + Sync + 'static>(
|
||||
cfg: ServeConfig<P>,
|
||||
pub fn render_ssr(
|
||||
cfg: ServeConfig,
|
||||
virtual_dom_factory: impl Fn() -> VirtualDom + Send + Sync + 'static,
|
||||
) -> impl Filter<Extract = (impl Reply,), Error = warp::Rejection> + Clone {
|
||||
warp::get()
|
||||
.and(request_parts())
|
||||
.and(with_ssr_state(&cfg))
|
||||
.then(move |parts: http::request::Parts, renderer: SSRState| {
|
||||
let route = parts.uri.path().to_string();
|
||||
let parts = Arc::new(RwLock::new(parts));
|
||||
let cfg = cfg.clone();
|
||||
async move {
|
||||
let server_context = DioxusServerContext::new(parts);
|
||||
.and(with_ssr_state(&cfg, virtual_dom_factory))
|
||||
.then(
|
||||
move |parts: http::request::Parts,
|
||||
(renderer, virtual_dom_factory): (
|
||||
SSRState,
|
||||
Arc<dyn Fn() -> VirtualDom + Send + Sync + 'static>,
|
||||
)| {
|
||||
let route = parts.uri.path().to_string();
|
||||
let parts = Arc::new(RwLock::new(parts));
|
||||
let cfg = cfg.clone();
|
||||
async move {
|
||||
let server_context = DioxusServerContext::new(parts);
|
||||
|
||||
match renderer.render(route, &cfg, &server_context).await {
|
||||
Ok(rendered) => {
|
||||
let crate::render::RenderResponse { html, freshness } = rendered;
|
||||
match renderer
|
||||
.render(route, &cfg, move || virtual_dom_factory(), &server_context)
|
||||
.await
|
||||
{
|
||||
Ok(rendered) => {
|
||||
let crate::render::RenderResponse { html, freshness } = rendered;
|
||||
|
||||
let mut res = Response::builder()
|
||||
.header("Content-Type", "text/html")
|
||||
.body(html)
|
||||
.unwrap();
|
||||
let mut res = Response::builder()
|
||||
.header("Content-Type", "text/html")
|
||||
.body(html)
|
||||
.unwrap();
|
||||
|
||||
let headers_mut = res.headers_mut();
|
||||
let headers = server_context.response_parts().unwrap().headers.clone();
|
||||
for (key, value) in headers.iter() {
|
||||
headers_mut.insert(key, value.clone());
|
||||
let headers_mut = res.headers_mut();
|
||||
let headers = server_context.response_parts().unwrap().headers.clone();
|
||||
for (key, value) in headers.iter() {
|
||||
headers_mut.insert(key, value.clone());
|
||||
}
|
||||
freshness.write(headers_mut);
|
||||
|
||||
res
|
||||
}
|
||||
Err(err) => {
|
||||
tracing::error!("Failed to render ssr: {}", err);
|
||||
Response::builder()
|
||||
.status(500)
|
||||
.body("Failed to render ssr".into())
|
||||
.unwrap()
|
||||
}
|
||||
freshness.write(headers_mut);
|
||||
|
||||
res
|
||||
}
|
||||
Err(err) => {
|
||||
tracing::error!("Failed to render ssr: {}", err);
|
||||
Response::builder()
|
||||
.status(500)
|
||||
.body("Failed to render ssr".into())
|
||||
.unwrap()
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
/// An extractor for the request parts (used in [DioxusServerContext]). This will extract the method, uri, query, and headers from the request.
|
||||
@@ -273,11 +291,20 @@ pub fn request_parts(
|
||||
})
|
||||
}
|
||||
|
||||
fn with_ssr_state<P: Clone + serde::Serialize + Send + Sync + 'static>(
|
||||
cfg: &ServeConfig<P>,
|
||||
) -> impl Filter<Extract = (SSRState,), Error = std::convert::Infallible> + Clone {
|
||||
fn with_ssr_state(
|
||||
cfg: &ServeConfig,
|
||||
virtual_dom_factory: impl Fn() -> VirtualDom + Send + Sync + 'static,
|
||||
) -> impl Filter<
|
||||
Extract = ((
|
||||
SSRState,
|
||||
Arc<dyn Fn() -> VirtualDom + Send + Sync + 'static>,
|
||||
),),
|
||||
Error = std::convert::Infallible,
|
||||
> + Clone {
|
||||
let renderer = SSRState::new(cfg);
|
||||
warp::any().map(move || renderer.clone())
|
||||
let virtual_dom_factory =
|
||||
Arc::new(virtual_dom_factory) as Arc<dyn Fn() -> VirtualDom + Send + Sync + 'static>;
|
||||
warp::any().map(move || (renderer.clone(), virtual_dom_factory.clone()))
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
||||
@@ -170,15 +170,19 @@ impl Config {
|
||||
let router = {
|
||||
// Serve the dist folder and the index.html file
|
||||
let serve_dir = warp::fs::dir(cfg.assets_path);
|
||||
let build_virtual_dom = Arc::new(build_virtual_dom);
|
||||
|
||||
router
|
||||
.or(connect_hot_reload())
|
||||
// Then the index route
|
||||
.or(warp::path::end().and(render_ssr(cfg.clone())))
|
||||
.or(warp::path::end().and(render_ssr(cfg.clone(), {
|
||||
let build_virtual_dom = build_virtual_dom.clone();
|
||||
move || build_virtual_dom()
|
||||
})))
|
||||
// Then the static assets
|
||||
.or(serve_dir)
|
||||
// Then all other routes
|
||||
.or(render_ssr(cfg))
|
||||
.or(render_ssr(cfg, move || build_virtual_dom()))
|
||||
};
|
||||
warp::serve(router.boxed().with(warp::filters::compression::gzip()))
|
||||
.run(addr)
|
||||
|
||||
Reference in new issue
Block a user