mirror of
https://github.com/leptos-rs/leptos
synced 2024-11-10 06:44:17 +00:00
Leptos can now generate routes and provide them to the Axum router. More
testing and Actix version to come
This commit is contained in:
parent
63b1837315
commit
677e4f2540
6 changed files with 85 additions and 9 deletions
|
@ -31,7 +31,7 @@ cfg_if! {
|
|||
let addr = conf.leptos_options.site_address.clone();
|
||||
println!("BEFFOORE");
|
||||
let routes = generate_route_list(|cx| view! { cx, <TodoApp/> });
|
||||
println!("HIIIIIIIIIIII");
|
||||
|
||||
println!("Routes: {:#?}", routes);
|
||||
|
||||
HttpServer::new(move || {
|
||||
|
|
|
@ -92,6 +92,7 @@ pub async fn delete_todo(id: u16) -> Result<(), ServerFnError> {
|
|||
|
||||
#[component]
|
||||
pub fn TodoApp(cx: Scope) -> impl IntoView {
|
||||
provide_meta_context(cx);
|
||||
view! {
|
||||
cx,
|
||||
<Stylesheet id="leptos" href="./target/site/pkg/todo_app_sqlite.css"/>
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
use cfg_if::cfg_if;
|
||||
use leptos::*;
|
||||
|
||||
// boilerplate to run in different modes
|
||||
cfg_if! {
|
||||
if #[cfg(feature = "ssr")] {
|
||||
|
@ -13,12 +12,18 @@ if #[cfg(feature = "ssr")] {
|
|||
use todo_app_sqlite_axum::*;
|
||||
use http::StatusCode;
|
||||
use tower_http::services::ServeDir;
|
||||
use tokio::{sync::RwLock, task::spawn_blocking, task::LocalSet};
|
||||
use leptos_axum::{generate_route_list, LeptosRoutes};
|
||||
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
simple_logger::init_with_level(log::Level::Debug).expect("couldn't initialize logging");
|
||||
|
||||
let mut conn = db().await.expect("couldn't connect to DB");
|
||||
let conn = db().await.expect("couldn't connect to DB");
|
||||
/* sqlx::migrate!()
|
||||
.run(&mut conn)
|
||||
.await
|
||||
|
@ -53,13 +58,18 @@ if #[cfg(feature = "ssr")] {
|
|||
)
|
||||
}
|
||||
|
||||
let routes = generate_route_list(|cx| view! { cx, <TodoApp/> }).await;
|
||||
println!("Routes_Outside: {:#?}",&routes);
|
||||
|
||||
|
||||
// build our application with a route
|
||||
let app = Router::new()
|
||||
let mut app = Router::new()
|
||||
.route("/api/*fn_name", post(leptos_axum::handle_server_fns))
|
||||
.nest_service("/pkg", pkg_service) // Only need if using wasm-pack. Can be deleted if using cargo-leptos
|
||||
.nest_service(&bundle_path, cargo_leptos_service) // Only needed if using cargo-leptos. Can be deleted if using wasm-pack and cargo-run
|
||||
.nest_service("/static", static_service)
|
||||
.fallback(leptos_axum::render_app_to_stream(leptos_options, |cx| view! { cx, <TodoApp/> }));
|
||||
.leptos_routes(leptos_options, routes, |cx| view! { cx, <TodoApp/> } );
|
||||
|
||||
|
||||
// run our app with hyper
|
||||
// `axum::Server` is a re-export of `hyper::Server`
|
||||
|
|
|
@ -39,9 +39,11 @@ cfg_if! {
|
|||
pub async fn get_todos(cx: Scope) -> Result<Vec<Todo>, ServerFnError> {
|
||||
// this is just an example of how to access server context injected in the handlers
|
||||
// http::Request doesn't implement Clone, so more work will be needed to do use_context() on this
|
||||
let req_parts = use_context::<leptos_axum::RequestParts>(cx).unwrap();
|
||||
println!("\ncalling server fn");
|
||||
let req_parts = use_context::<leptos_axum::RequestParts>(cx);
|
||||
|
||||
if let Some(req_parts) = req_parts{
|
||||
println!("Uri = {:?}", req_parts.uri);
|
||||
}
|
||||
|
||||
use futures::TryStreamExt;
|
||||
|
||||
|
@ -105,6 +107,7 @@ pub async fn delete_todo(id: u16) -> Result<(), ServerFnError> {
|
|||
|
||||
#[component]
|
||||
pub fn TodoApp(cx: Scope) -> impl IntoView {
|
||||
provide_meta_context(cx);
|
||||
view! {
|
||||
cx,
|
||||
<Stylesheet id="leptos" href="./target/site/pkg/todo_app_sqlite_axum.css"/>
|
||||
|
|
|
@ -3,6 +3,7 @@ use axum::{
|
|||
extract::Path,
|
||||
http::{header::HeaderName, header::HeaderValue, HeaderMap, Request, StatusCode},
|
||||
response::IntoResponse,
|
||||
routing::get,
|
||||
};
|
||||
use futures::{Future, SinkExt, Stream, StreamExt};
|
||||
use http::{header, method::Method, uri::Uri, version::Version, Response};
|
||||
|
@ -11,7 +12,7 @@ use leptos::*;
|
|||
use leptos_meta::MetaContext;
|
||||
use leptos_router::*;
|
||||
use std::{io, pin::Pin, sync::Arc};
|
||||
use tokio::{sync::RwLock, task::spawn_blocking};
|
||||
use tokio::{sync::RwLock, task::spawn_blocking, task::LocalSet};
|
||||
|
||||
/// A struct to hold the parts of the incoming Request. Since `http::Request` isn't cloneable, we're forced
|
||||
/// to construct this for Leptos to use in Axum
|
||||
|
@ -499,3 +500,64 @@ where
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn generate_route_list<IV>(app_fn: impl FnOnce(Scope) -> IV + 'static) -> Vec<String>
|
||||
where
|
||||
IV: IntoView + 'static,
|
||||
{
|
||||
#[derive(Default, Clone, Debug)]
|
||||
pub struct Routes(pub Arc<RwLock<Vec<String>>>);
|
||||
|
||||
let routes = Routes::default();
|
||||
let routes_inner = routes.clone();
|
||||
|
||||
let local = LocalSet::new();
|
||||
// Run the local task set.
|
||||
|
||||
local
|
||||
.run_until(async move {
|
||||
tokio::task::spawn_local(async move {
|
||||
let routes = leptos_router::generate_route_list_inner(app_fn);
|
||||
let mut writable = routes_inner.0.write().await;
|
||||
*writable = routes;
|
||||
})
|
||||
.await
|
||||
.unwrap();
|
||||
})
|
||||
.await;
|
||||
|
||||
let routes = routes.0.read().await.to_owned();
|
||||
routes.iter().map(|s| s.replace("", "/")).collect()
|
||||
}
|
||||
|
||||
pub trait LeptosRoutes {
|
||||
fn leptos_routes<IV>(
|
||||
self,
|
||||
options: LeptosOptions,
|
||||
paths: Vec<String>,
|
||||
app_fn: impl Fn(leptos::Scope) -> IV + Clone + Send + 'static,
|
||||
) -> Self
|
||||
where
|
||||
IV: IntoView + 'static;
|
||||
}
|
||||
|
||||
impl LeptosRoutes for axum::Router {
|
||||
fn leptos_routes<IV>(
|
||||
self,
|
||||
options: LeptosOptions,
|
||||
paths: Vec<String>,
|
||||
app_fn: impl Fn(leptos::Scope) -> IV + Clone + Send + 'static,
|
||||
) -> Self
|
||||
where
|
||||
IV: IntoView + 'static,
|
||||
{
|
||||
let mut router = self;
|
||||
for path in paths.iter() {
|
||||
router = router.route(
|
||||
path,
|
||||
get(render_app_to_stream(options.clone(), app_fn.clone())),
|
||||
);
|
||||
}
|
||||
router
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ pub struct PossibleBranchContext(pub(crate) Rc<RefCell<Vec<Branch>>>);
|
|||
|
||||
/// Generates a list of all routes this application could possibly serve.
|
||||
#[cfg(feature = "ssr")]
|
||||
pub fn generate_route_list<IV>(app_fn: impl FnOnce(Scope) -> IV + 'static) -> Vec<String>
|
||||
pub fn generate_route_list_inner<IV>(app_fn: impl FnOnce(Scope) -> IV + 'static) -> Vec<String>
|
||||
where
|
||||
IV: IntoView + 'static,
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue