Merge branch 'DioxusLabs:master' into fix-event-bubbling

This commit is contained in:
ealmloff authored and GitHub committed 2023-12-16 06:34:00 -06:00
commit 56478d1856
101 files changed
+1705 -466

No files matched your search

@@ -24,6 +24,7 @@ fn app(cx: Scope<AppProps>) -> Element {
let mut count = use_state(cx, || 0);
let text = use_state(cx, || "...".to_string());
let eval = use_eval(cx);
cx.render(rsx! {
div {
@@ -369,15 +369,65 @@ fn apply_request_parts_to_response<B>(
}
}
/// SSR renderer handler for Axum
pub async fn render_handler<P: Clone + serde::Serialize + Send + Sync + 'static>(
State((cfg, ssr_state)): State<(ServeConfig<P>, SSRState)>,
/// SSR renderer handler for Axum with added context injection.
///
/// # Example
/// ```rust,no_run
/// #![allow(non_snake_case)]
/// use std::sync::{Arc, Mutex};
///
/// use axum::routing::get;
/// use dioxus::prelude::*;
/// use dioxus_fullstack::{axum_adapter::render_handler_with_context, prelude::*};
///
/// fn app(cx: Scope) -> Element {
/// render! {
/// "hello!"
/// }
/// }
///
/// #[tokio::main]
/// async fn main() {
/// let cfg = ServeConfigBuilder::new(app, ())
/// .assets_path("dist")
/// .build();
/// let ssr_state = SSRState::new(&cfg);
///
/// // This could be any state you want to be accessible from your server
/// // functions using `[DioxusServerContext::get]`.
/// let state = Arc::new(Mutex::new("state".to_string()));
///
/// let addr = std::net::SocketAddr::from(([127, 0, 0, 1], 8080));
/// axum::Server::bind(&addr)
/// .serve(
/// axum::Router::new()
/// // Register server functions, etc.
/// // Note you probably want to use `register_server_fns_with_handler`
/// // to inject the context into server functions running outside
/// // of an SSR render context.
/// .fallback(get(render_handler_with_context).with_state((
/// move |ctx| ctx.insert(state.clone()).unwrap(),
/// cfg,
/// ssr_state,
/// )))
/// .into_make_service(),
/// )
/// .await
/// .unwrap();
/// }
/// ```
pub async fn render_handler_with_context<
P: Clone + serde::Serialize + Send + Sync + 'static,
F: FnMut(&mut DioxusServerContext),
>(
State((mut inject_context, cfg, ssr_state)): State<(F, ServeConfig<P>, SSRState)>,
request: Request<Body>,
) -> impl IntoResponse {
let (parts, _) = request.into_parts();
let url = parts.uri.path_and_query().unwrap().to_string();
let parts: Arc<RwLock<http::request::Parts>> = Arc::new(RwLock::new(parts.into()));
let server_context = DioxusServerContext::new(parts.clone());
let mut server_context = DioxusServerContext::new(parts.clone());
inject_context(&mut server_context);
match ssr_state.render(url, &cfg, &server_context).await {
Ok(rendered) => {
@@ -395,6 +445,14 @@ pub async fn render_handler<P: Clone + serde::Serialize + Send + Sync + 'static>
}
}
/// SSR renderer handler for Axum
pub async fn render_handler<P: Clone + serde::Serialize + Send + Sync + 'static>(
State((cfg, ssr_state)): State<(ServeConfig<P>, SSRState)>,
request: Request<Body>,
) -> impl IntoResponse {
render_handler_with_context(State((|_: &mut _| (), cfg, ssr_state)), request).await
}
fn report_err<E: std::fmt::Display>(e: E) -> Response<BoxBody> {
Response::builder()
.status(StatusCode::INTERNAL_SERVER_ERROR)
+19 -19
View File
@@ -89,26 +89,26 @@ impl Service for ServerFnHandler {
let parts = Arc::new(RwLock::new(parts));
// Because the future returned by `server_fn_handler` is `Send`, and the future returned by this function must be send, we need to spawn a new runtime
let (resp_tx, resp_rx) = tokio::sync::oneshot::channel();
let pool = get_local_pool();
pool.spawn_pinned({
let function = function.clone();
let mut server_context = server_context.clone();
server_context.parts = parts;
move || async move {
let data = match function.encoding() {
Encoding::Url | Encoding::Cbor => &body,
Encoding::GetJSON | Encoding::GetCBOR => &query,
};
let server_function_future = function.call((), data);
let server_function_future =
ProvideServerContext::new(server_function_future, server_context.clone());
let resp = server_function_future.await;
resp_tx.send(resp).unwrap();
}
});
let result = resp_rx.await.unwrap();
let result = pool
.spawn_pinned({
let function = function.clone();
let mut server_context = server_context.clone();
server_context.parts = parts;
move || async move {
let data = match function.encoding() {
Encoding::Url | Encoding::Cbor => &body,
Encoding::GetJSON | Encoding::GetCBOR => &query,
};
let server_function_future = function.call((), data);
let server_function_future = ProvideServerContext::new(
server_function_future,
server_context.clone(),
);
server_function_future.await
}
})
.await?;
let mut res = http::Response::builder();
// Set the headers from the server context
+5
View File
@@ -3,7 +3,9 @@ use tracing_futures::Instrument;
use http::{Request, Response};
/// A layer that wraps a service. This can be used to add additional information to the request, or response on top of some other service
pub trait Layer: Send + Sync + 'static {
/// Wrap a boxed service with this layer
fn layer(&self, inner: BoxedService) -> BoxedService;
}
@@ -17,7 +19,9 @@ where
}
}
/// A service is a function that takes a request and returns an async response
pub trait Service {
/// Run the service and produce a future that resolves to a response
fn run(
&mut self,
req: http::Request<hyper::body::Body>,
@@ -55,6 +59,7 @@ where
}
}
/// A boxed service is a type-erased service that can be used without knowing the underlying type
pub struct BoxedService(pub Box<dyn Service + Send>);
impl tower::Service<http::Request<hyper::body::Body>> for BoxedService {
+2
View File
@@ -40,6 +40,8 @@ pub mod prelude {
#[cfg(not(feature = "ssr"))]
pub use crate::html_storage::deserialize::get_root_props_from_document;
pub use crate::launch::LaunchBuilder;
#[cfg(feature = "ssr")]
pub use crate::layer::{Layer, Service};
#[cfg(all(feature = "ssr", feature = "router"))]
pub use crate::render::pre_cache_static_routes_with_props;
#[cfg(feature = "ssr")]
+2
View File
@@ -45,6 +45,8 @@ impl SsrRendererPool {
.expect("couldn't spawn runtime")
.block_on(async move {
let mut vdom = VirtualDom::new_with_props(component, props);
// Make sure the evaluator is initialized
dioxus_ssr::eval::init_eval(vdom.base_scope());
let mut to = WriteBuffer { buffer: Vec::new() };
// before polling the future, we need to set the context
let prev_context =
+1 -1
View File
@@ -53,7 +53,7 @@ fn default_external_navigation_handler() -> fn(Scope) -> Element {
dioxus_router::prelude::FailureExternalNavigation
}
/// The configeration for the router
/// The configuration for the router
#[derive(Props, serde::Serialize, serde::Deserialize)]
pub struct FullstackRouterConfig<R>
where