mirror of
https://github.com/leptos-rs/leptos.git
synced 2025-12-27 09:54:41 -05:00
Merge remote-tracking branch 'origin' into leptos_0.8
This commit is contained in:
@@ -21,10 +21,10 @@ leptos_macro = { workspace = true, features = ["actix"] }
|
||||
leptos_meta = { workspace = true, features = ["nonce"] }
|
||||
leptos_router = { workspace = true, features = ["ssr"] }
|
||||
server_fn = { workspace = true, features = ["actix"] }
|
||||
serde_json = "1.0"
|
||||
serde_json = { workspace = true }
|
||||
parking_lot = "0.12.3"
|
||||
tracing = { version = "0.1", optional = true }
|
||||
tokio = { version = "1.41", features = ["rt", "fs"] }
|
||||
tokio = { version = "1.43", features = ["rt", "fs"] }
|
||||
send_wrapper = "0.6.0"
|
||||
dashmap = "6"
|
||||
once_cell = "1"
|
||||
|
||||
@@ -274,14 +274,13 @@ pub fn redirect(path: &str) {
|
||||
///
|
||||
/// This can then be set up at an appropriate route in your application:
|
||||
///
|
||||
/// ```
|
||||
/// ```no_run
|
||||
/// use actix_web::*;
|
||||
///
|
||||
/// fn register_server_functions() {
|
||||
/// // call ServerFn::register() for each of the server functions you've defined
|
||||
/// }
|
||||
///
|
||||
/// # if false { // don't actually try to run a server in a doctest...
|
||||
/// #[actix_web::main]
|
||||
/// async fn main() -> std::io::Result<()> {
|
||||
/// // make sure you actually register your server functions
|
||||
@@ -297,7 +296,6 @@ pub fn redirect(path: &str) {
|
||||
/// .run()
|
||||
/// .await
|
||||
/// }
|
||||
/// # }
|
||||
/// ```
|
||||
///
|
||||
/// ## Provided Context Types
|
||||
@@ -432,7 +430,7 @@ pub fn handle_server_fns_with_context(
|
||||
/// but requires some client-side JavaScript.
|
||||
///
|
||||
/// This can then be set up at an appropriate route in your application:
|
||||
/// ```
|
||||
/// ```no_run
|
||||
/// use actix_web::{App, HttpServer};
|
||||
/// use leptos::prelude::*;
|
||||
/// use leptos_router::Method;
|
||||
@@ -443,7 +441,6 @@ pub fn handle_server_fns_with_context(
|
||||
/// view! { <main>"Hello, world!"</main> }
|
||||
/// }
|
||||
///
|
||||
/// # if false { // don't actually try to run a server in a doctest...
|
||||
/// #[actix_web::main]
|
||||
/// async fn main() -> std::io::Result<()> {
|
||||
/// let conf = get_configuration(Some("Cargo.toml")).unwrap();
|
||||
@@ -463,7 +460,6 @@ pub fn handle_server_fns_with_context(
|
||||
/// .run()
|
||||
/// .await
|
||||
/// }
|
||||
/// # }
|
||||
/// ```
|
||||
///
|
||||
/// ## Provided Context Types
|
||||
@@ -491,7 +487,7 @@ where
|
||||
/// sending down its HTML. The app will become interactive once it has fully loaded.
|
||||
///
|
||||
/// This can then be set up at an appropriate route in your application:
|
||||
/// ```
|
||||
/// ```no_run
|
||||
/// use actix_web::{App, HttpServer};
|
||||
/// use leptos::prelude::*;
|
||||
/// use leptos_router::Method;
|
||||
@@ -502,7 +498,6 @@ where
|
||||
/// view! { <main>"Hello, world!"</main> }
|
||||
/// }
|
||||
///
|
||||
/// # if false { // don't actually try to run a server in a doctest...
|
||||
/// #[actix_web::main]
|
||||
/// async fn main() -> std::io::Result<()> {
|
||||
/// let conf = get_configuration(Some("Cargo.toml")).unwrap();
|
||||
@@ -525,7 +520,6 @@ where
|
||||
/// .run()
|
||||
/// .await
|
||||
/// }
|
||||
/// # }
|
||||
/// ```
|
||||
///
|
||||
/// ## Provided Context Types
|
||||
@@ -551,7 +545,7 @@ where
|
||||
/// `async` resources have loaded.
|
||||
///
|
||||
/// This can then be set up at an appropriate route in your application:
|
||||
/// ```
|
||||
/// ```no_run
|
||||
/// use actix_web::{App, HttpServer};
|
||||
/// use leptos::prelude::*;
|
||||
/// use leptos_router::Method;
|
||||
@@ -562,7 +556,6 @@ where
|
||||
/// view! { <main>"Hello, world!"</main> }
|
||||
/// }
|
||||
///
|
||||
/// # if false { // don't actually try to run a server in a doctest...
|
||||
/// #[actix_web::main]
|
||||
/// async fn main() -> std::io::Result<()> {
|
||||
/// let conf = get_configuration(Some("Cargo.toml")).unwrap();
|
||||
@@ -582,7 +575,6 @@ where
|
||||
/// .run()
|
||||
/// .await
|
||||
/// }
|
||||
/// # }
|
||||
/// ```
|
||||
///
|
||||
/// ## Provided Context Types
|
||||
|
||||
@@ -24,14 +24,14 @@ leptos_router = { workspace = true, features = ["ssr"] }
|
||||
leptos_integration_utils = { workspace = true }
|
||||
once_cell = "1"
|
||||
parking_lot = "0.12.3"
|
||||
tokio = { version = "1.41", default-features = false }
|
||||
tokio = { version = "1.43", default-features = false }
|
||||
tower = { version = "0.5.1", features = ["util"] }
|
||||
tower-http = "0.6.2"
|
||||
tracing = { version = "0.1.41", optional = true }
|
||||
|
||||
[dev-dependencies]
|
||||
axum = "0.8.1"
|
||||
tokio = { version = "1.41", features = ["net", "rt-multi-thread"] }
|
||||
tokio = { version = "1.43", features = ["net", "rt-multi-thread"] }
|
||||
|
||||
[features]
|
||||
wasm = []
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#![forbid(unsafe_code)]
|
||||
#![deny(missing_docs)]
|
||||
#![allow(clippy::type_complexity)]
|
||||
|
||||
//! Provides functions to easily integrate Leptos with Axum.
|
||||
//!
|
||||
@@ -278,12 +279,11 @@ pub fn generate_request_and_parts(
|
||||
///
|
||||
/// This can then be set up at an appropriate route in your application:
|
||||
///
|
||||
/// ```
|
||||
/// ```no_run
|
||||
/// use axum::{handler::Handler, routing::post, Router};
|
||||
/// use leptos::prelude::*;
|
||||
/// use std::net::SocketAddr;
|
||||
///
|
||||
/// # if false { // don't actually try to run a server in a doctest...
|
||||
/// #[cfg(feature = "default")]
|
||||
/// #[tokio::main]
|
||||
/// async fn main() {
|
||||
@@ -299,7 +299,9 @@ pub fn generate_request_and_parts(
|
||||
/// .await
|
||||
/// .unwrap();
|
||||
/// }
|
||||
/// # }
|
||||
///
|
||||
/// # #[cfg(not(feature = "default"))]
|
||||
/// # fn main() { }
|
||||
/// ```
|
||||
/// Leptos provides a generic implementation of `handle_server_fns`. If access to more specific parts of the Request is desired,
|
||||
/// you can specify your own server fn handler based on this one and give it it's own route in the server macro.
|
||||
@@ -440,7 +442,7 @@ pub type PinnedHtmlStream =
|
||||
/// to route it using [leptos_router], serving an HTML stream of your application.
|
||||
///
|
||||
/// This can then be set up at an appropriate route in your application:
|
||||
/// ```
|
||||
/// ```no_run
|
||||
/// use axum::{handler::Handler, Router};
|
||||
/// use leptos::{config::get_configuration, prelude::*};
|
||||
/// use std::{env, net::SocketAddr};
|
||||
@@ -450,7 +452,6 @@ pub type PinnedHtmlStream =
|
||||
/// view! { <main>"Hello, world!"</main> }
|
||||
/// }
|
||||
///
|
||||
/// # if false { // don't actually try to run a server in a doctest...
|
||||
/// #[cfg(feature = "default")]
|
||||
/// #[tokio::main]
|
||||
/// async fn main() {
|
||||
@@ -469,7 +470,9 @@ pub type PinnedHtmlStream =
|
||||
/// .await
|
||||
/// .unwrap();
|
||||
/// }
|
||||
/// # }
|
||||
///
|
||||
/// # #[cfg(not(feature = "default"))]
|
||||
/// # fn main() { }
|
||||
/// ```
|
||||
///
|
||||
/// ## Provided Context Types
|
||||
@@ -528,7 +531,7 @@ where
|
||||
/// sending down its HTML. The app will become interactive once it has fully loaded.
|
||||
///
|
||||
/// This can then be set up at an appropriate route in your application:
|
||||
/// ```
|
||||
/// ```no_run
|
||||
/// use axum::{handler::Handler, Router};
|
||||
/// use leptos::{config::get_configuration, prelude::*};
|
||||
/// use std::{env, net::SocketAddr};
|
||||
@@ -538,7 +541,6 @@ where
|
||||
/// view! { <main>"Hello, world!"</main> }
|
||||
/// }
|
||||
///
|
||||
/// # if false { // don't actually try to run a server in a doctest...
|
||||
/// #[cfg(feature = "default")]
|
||||
/// #[tokio::main]
|
||||
/// async fn main() {
|
||||
@@ -557,7 +559,9 @@ where
|
||||
/// .await
|
||||
/// .unwrap();
|
||||
/// }
|
||||
/// # }
|
||||
///
|
||||
/// # #[cfg(not(feature = "default"))]
|
||||
/// # fn main() { }
|
||||
/// ```
|
||||
///
|
||||
/// ## Provided Context Types
|
||||
@@ -941,7 +945,7 @@ fn provide_contexts(
|
||||
/// `async` resources have loaded.
|
||||
///
|
||||
/// This can then be set up at an appropriate route in your application:
|
||||
/// ```
|
||||
/// ```no_run
|
||||
/// use axum::{handler::Handler, Router};
|
||||
/// use leptos::{config::get_configuration, prelude::*};
|
||||
/// use std::{env, net::SocketAddr};
|
||||
@@ -951,7 +955,6 @@ fn provide_contexts(
|
||||
/// view! { <main>"Hello, world!"</main> }
|
||||
/// }
|
||||
///
|
||||
/// # if false { // don't actually try to run a server in a doctest...
|
||||
/// #[cfg(feature = "default")]
|
||||
/// #[tokio::main]
|
||||
/// async fn main() {
|
||||
@@ -971,7 +974,9 @@ fn provide_contexts(
|
||||
/// .await
|
||||
/// .unwrap();
|
||||
/// }
|
||||
/// # }
|
||||
///
|
||||
/// # #[cfg(not(feature = "default"))]
|
||||
/// # fn main() { }
|
||||
/// ```
|
||||
///
|
||||
/// ## Provided Context Types
|
||||
@@ -1988,7 +1993,8 @@ where
|
||||
/// This is provided as a convenience, but is a fairly simple function. If you need to adapt it,
|
||||
/// simply reuse the source code of this function in your own application.
|
||||
#[cfg(feature = "default")]
|
||||
pub fn file_and_error_handler<S, IV>(
|
||||
pub fn file_and_error_handler_with_context<S, IV>(
|
||||
additional_context: impl Fn() + 'static + Clone + Send,
|
||||
shell: fn(LeptosOptions) -> IV,
|
||||
) -> impl Fn(
|
||||
Uri,
|
||||
@@ -2004,40 +2010,68 @@ where
|
||||
LeptosOptions: FromRef<S>,
|
||||
{
|
||||
move |uri: Uri, State(state): State<S>, req: Request<Body>| {
|
||||
Box::pin(async move {
|
||||
let options = LeptosOptions::from_ref(&state);
|
||||
let res = get_static_file(uri, &options.site_root, req.headers());
|
||||
let res = res.await.unwrap();
|
||||
Box::pin({
|
||||
let additional_context = additional_context.clone();
|
||||
async move {
|
||||
let options = LeptosOptions::from_ref(&state);
|
||||
let res =
|
||||
get_static_file(uri, &options.site_root, req.headers());
|
||||
let res = res.await.unwrap();
|
||||
|
||||
if res.status() == StatusCode::OK {
|
||||
res.into_response()
|
||||
} else {
|
||||
let mut res = handle_response_inner(
|
||||
move || {
|
||||
provide_context(state.clone());
|
||||
},
|
||||
move || shell(options),
|
||||
req,
|
||||
|app, chunks| {
|
||||
Box::pin(async move {
|
||||
let app = app
|
||||
.to_html_stream_in_order()
|
||||
.collect::<String>()
|
||||
.await;
|
||||
let chunks = chunks();
|
||||
Box::pin(once(async move { app }).chain(chunks))
|
||||
as PinnedStream<String>
|
||||
})
|
||||
},
|
||||
)
|
||||
.await;
|
||||
*res.status_mut() = StatusCode::NOT_FOUND;
|
||||
res
|
||||
if res.status() == StatusCode::OK {
|
||||
res.into_response()
|
||||
} else {
|
||||
let mut res = handle_response_inner(
|
||||
move || {
|
||||
additional_context();
|
||||
provide_context(state.clone());
|
||||
},
|
||||
move || shell(options),
|
||||
req,
|
||||
|app, chunks| {
|
||||
Box::pin(async move {
|
||||
let app = app
|
||||
.to_html_stream_in_order()
|
||||
.collect::<String>()
|
||||
.await;
|
||||
let chunks = chunks();
|
||||
Box::pin(once(async move { app }).chain(chunks))
|
||||
as PinnedStream<String>
|
||||
})
|
||||
},
|
||||
)
|
||||
.await;
|
||||
*res.status_mut() = StatusCode::NOT_FOUND;
|
||||
res
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// A reasonable handler for serving static files (like JS/WASM/CSS) and 404 errors.
|
||||
///
|
||||
/// This is provided as a convenience, but is a fairly simple function. If you need to adapt it,
|
||||
/// simply reuse the source code of this function in your own application.
|
||||
#[cfg(feature = "default")]
|
||||
pub fn file_and_error_handler<S, IV>(
|
||||
shell: fn(LeptosOptions) -> IV,
|
||||
) -> impl Fn(
|
||||
Uri,
|
||||
State<S>,
|
||||
Request<Body>,
|
||||
) -> Pin<Box<dyn Future<Output = Response<Body>> + Send + 'static>>
|
||||
+ Clone
|
||||
+ Send
|
||||
+ 'static
|
||||
where
|
||||
IV: IntoView + 'static,
|
||||
S: Send + Sync + Clone + 'static,
|
||||
LeptosOptions: FromRef<S>,
|
||||
{
|
||||
file_and_error_handler_with_context(move || (), shell)
|
||||
}
|
||||
|
||||
#[cfg(feature = "default")]
|
||||
async fn get_static_file(
|
||||
uri: Uri,
|
||||
|
||||
Reference in New Issue
Block a user