dioxus_fullstack/server/
launch.rs1use std::any::Any;
4
5use axum::{
6 body::Body,
7 extract::{Request, State},
8 response::IntoResponse,
9};
10use dioxus_cli_config::base_path;
11use dioxus_lib::prelude::*;
12
13use crate::server::{render_handler, RenderHandleState, SSRState};
14
15#[allow(unused)]
17pub fn launch(
18 root: fn() -> Element,
19 contexts: Vec<Box<dyn Fn() -> Box<dyn Any> + Send + Sync>>,
20 platform_config: Vec<Box<dyn Any>>,
21) -> ! {
22 use crate::{ServeConfig, ServeConfigBuilder};
23
24 #[cfg(not(target_arch = "wasm32"))]
25 tokio::runtime::Runtime::new()
26 .unwrap()
27 .block_on(async move {
28 let platform_config = platform_config
29 .into_iter()
30 .find_map(|cfg| {
31 cfg.downcast::<ServeConfig>()
32 .map(|cfg| Result::Ok(*cfg))
33 .or_else(|cfg| {
34 cfg.downcast::<ServeConfigBuilder>()
35 .map(|builder| builder.build())
36 })
37 .ok()
38 })
39 .unwrap_or_else(ServeConfig::new);
40
41 let platform_config = platform_config.map(|mut cfg| {
43 let mut contexts = contexts;
44 let cfg_context_providers = cfg.context_providers.clone();
45 for i in 0..cfg_context_providers.len() {
46 contexts.push(Box::new({
47 let cfg_context_providers = cfg_context_providers.clone();
48 move || (cfg_context_providers[i])()
49 }));
50 }
51 cfg.context_providers = std::sync::Arc::new(contexts);
52 cfg
53 });
54
55 let address = dioxus_cli_config::fullstack_address_or_localhost();
58
59 use crate::server::DioxusRouterExt;
60
61 struct TryIntoResult(Result<ServeConfig, crate::UnableToLoadIndex>);
62
63 impl TryInto<ServeConfig> for TryIntoResult {
64 type Error = crate::UnableToLoadIndex;
65
66 fn try_into(self) -> Result<ServeConfig, Self::Error> {
67 self.0
68 }
69 }
70
71 let mut base_path = base_path();
72 let config = platform_config.as_ref().ok().cloned();
73 let dioxus_router =
74 axum::Router::new().serve_dioxus_application(TryIntoResult(platform_config), root);
75 let mut router;
76 match base_path.as_deref() {
77 Some(base_path) => {
78 let base_path = base_path.trim_matches('/');
79 router = axum::Router::new().nest(&format!("/{base_path}/"), dioxus_router);
82 async fn root_render_handler(
83 state: State<RenderHandleState>,
84 mut request: Request<Body>,
85 ) -> impl IntoResponse {
86 *request.uri_mut() = "/".parse().unwrap();
88 render_handler(state, request).await
89 }
90 if let Some(cfg) = config {
91 let ssr_state = SSRState::new(&cfg);
92 router = router.route(
93 &format!("/{base_path}"),
94 axum::routing::method_routing::get(root_render_handler).with_state(
95 RenderHandleState::new(cfg, root).with_ssr_state(ssr_state),
96 ),
97 )
98 }
99 }
100 None => router = dioxus_router,
101 }
102
103 let router = router.into_make_service();
104 let listener = tokio::net::TcpListener::bind(address).await.unwrap();
105
106 axum::serve(listener, router).await.unwrap();
107 });
108
109 unreachable!("Launching a fullstack app should never return")
110}