mirror of
https://github.com/leptos-rs/leptos.git
synced 2026-01-11 11:48:06 -05:00
Compare commits
4 Commits
lazy-wasm-
...
remove-das
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0dc6b7b56b | ||
|
|
3a2700ac56 | ||
|
|
421ed40e9d | ||
|
|
588f6db557 |
27
Cargo.lock
generated
27
Cargo.lock
generated
@@ -845,20 +845,6 @@ dependencies = [
|
||||
"typenum",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dashmap"
|
||||
version = "6.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5041cc499144891f3790297212f32a74fb938e5136a14943f338ef9e0ae276cf"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"crossbeam-utils",
|
||||
"hashbrown 0.14.5",
|
||||
"lock_api",
|
||||
"once_cell",
|
||||
"parking_lot_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "data-encoding"
|
||||
version = "2.9.0"
|
||||
@@ -1465,12 +1451,6 @@ dependencies = [
|
||||
"byteorder",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.14.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.15.5"
|
||||
@@ -1947,7 +1927,6 @@ dependencies = [
|
||||
"actix-http",
|
||||
"actix-web",
|
||||
"any_spawner",
|
||||
"dashmap",
|
||||
"futures",
|
||||
"hydration_context",
|
||||
"leptos",
|
||||
@@ -1955,6 +1934,7 @@ dependencies = [
|
||||
"leptos_macro",
|
||||
"leptos_meta",
|
||||
"leptos_router",
|
||||
"or_poisoned",
|
||||
"parking_lot",
|
||||
"send_wrapper",
|
||||
"serde_json",
|
||||
@@ -1970,7 +1950,6 @@ version = "0.8.7"
|
||||
dependencies = [
|
||||
"any_spawner",
|
||||
"axum",
|
||||
"dashmap",
|
||||
"futures",
|
||||
"hydration_context",
|
||||
"leptos",
|
||||
@@ -1978,6 +1957,7 @@ dependencies = [
|
||||
"leptos_macro",
|
||||
"leptos_meta",
|
||||
"leptos_router",
|
||||
"or_poisoned",
|
||||
"parking_lot",
|
||||
"server_fn",
|
||||
"tachys",
|
||||
@@ -2920,7 +2900,6 @@ name = "reactive_stores"
|
||||
version = "0.3.1"
|
||||
dependencies = [
|
||||
"any_spawner",
|
||||
"dashmap",
|
||||
"guardian",
|
||||
"itertools",
|
||||
"leptos",
|
||||
@@ -3435,7 +3414,6 @@ dependencies = [
|
||||
"ciborium",
|
||||
"const-str",
|
||||
"const_format",
|
||||
"dashmap",
|
||||
"futures",
|
||||
"gloo-net",
|
||||
"http 1.4.0",
|
||||
@@ -3444,6 +3422,7 @@ dependencies = [
|
||||
"inventory",
|
||||
"js-sys",
|
||||
"multer",
|
||||
"or_poisoned",
|
||||
"pin-project-lite",
|
||||
"postcard",
|
||||
"reqwest",
|
||||
|
||||
@@ -89,7 +89,6 @@ actix-web = { default-features = false, version = "4.12.1" }
|
||||
tracing = { default-features = false, version = "0.1.44" }
|
||||
slotmap = { default-features = false, version = "1.1.1" }
|
||||
futures = { default-features = false, version = "0.3.31" }
|
||||
dashmap = { default-features = false, version = "6.1.0" }
|
||||
pin-project-lite = { default-features = false, version = "0.2.16" }
|
||||
send_wrapper = { default-features = false, version = "0.6.0" }
|
||||
tokio-test = { default-features = false, version = "0.4.4" }
|
||||
|
||||
@@ -37,7 +37,6 @@ web-sys = { version = "0.3.70", features = ["FileList", "File"] }
|
||||
strum = { version = "0.27.1", features = ["strum_macros", "derive"] }
|
||||
notify = { version = "8.0", optional = true }
|
||||
pin-project-lite = "0.2.14"
|
||||
dashmap = { version = "6.0", optional = true }
|
||||
async-broadcast = { version = "0.7.1", optional = true }
|
||||
bytecheck = "0.8.0"
|
||||
rkyv = { version = "0.8.8" }
|
||||
@@ -52,7 +51,6 @@ ssr = [
|
||||
"leptos/ssr",
|
||||
"dep:leptos_axum",
|
||||
"dep:notify",
|
||||
"dep:dashmap",
|
||||
"dep:async-broadcast",
|
||||
]
|
||||
|
||||
|
||||
@@ -422,7 +422,6 @@ pub fn FileUploadWithProgress() -> impl IntoView {
|
||||
#[cfg(feature = "ssr")]
|
||||
mod progress {
|
||||
use async_broadcast::{broadcast, Receiver, Sender};
|
||||
use dashmap::DashMap;
|
||||
use futures::Stream;
|
||||
use std::sync::LazyLock;
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ parking_lot = { workspace = true, default-features = true }
|
||||
tracing = { optional = true, workspace = true, default-features = true }
|
||||
tokio = { features = ["rt", "fs"], workspace = true, default-features = true }
|
||||
send_wrapper = { workspace = true, default-features = true }
|
||||
dashmap = { workspace = true, default-features = true }
|
||||
or_poisoned = { workspace = true, default-features = true }
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
rustdoc-args = ["--generate-link-to-definition"]
|
||||
|
||||
@@ -16,7 +16,6 @@ use actix_web::{
|
||||
web::{Data, Payload, ServiceConfig},
|
||||
*,
|
||||
};
|
||||
use dashmap::DashMap;
|
||||
use futures::{stream::once, Stream, StreamExt};
|
||||
use http::StatusCode;
|
||||
use hydration_context::SsrSharedContext;
|
||||
@@ -38,6 +37,7 @@ use leptos_router::{
|
||||
static_routes::{RegenerationFn, ResolvedStaticPath},
|
||||
ExpandOptionals, Method, PathSegment, RouteList, RouteListing, SsrMode,
|
||||
};
|
||||
use or_poisoned::OrPoisoned;
|
||||
use parking_lot::RwLock;
|
||||
use send_wrapper::SendWrapper;
|
||||
use server_fn::{
|
||||
@@ -45,7 +45,7 @@ use server_fn::{
|
||||
request::actix::ActixRequest,
|
||||
};
|
||||
use std::{
|
||||
collections::HashSet,
|
||||
collections::{HashMap, HashSet},
|
||||
fmt::{Debug, Display},
|
||||
future::Future,
|
||||
ops::{Deref, DerefMut},
|
||||
@@ -1222,8 +1222,9 @@ impl StaticRouteGenerator {
|
||||
}
|
||||
}
|
||||
|
||||
static STATIC_HEADERS: LazyLock<DashMap<String, ResponseOptions>> =
|
||||
LazyLock::new(DashMap::new);
|
||||
static STATIC_HEADERS: LazyLock<
|
||||
std::sync::RwLock<HashMap<String, ResponseOptions>>,
|
||||
> = LazyLock::new(Default::default);
|
||||
|
||||
fn was_404(owner: &Owner) -> bool {
|
||||
let resp = owner.with(|| expect_context::<ResponseOptions>());
|
||||
@@ -1255,7 +1256,10 @@ async fn write_static_route(
|
||||
html: &str,
|
||||
) -> Result<(), std::io::Error> {
|
||||
if let Some(options) = response_options {
|
||||
STATIC_HEADERS.insert(path.to_string(), options);
|
||||
STATIC_HEADERS
|
||||
.write()
|
||||
.or_poisoned()
|
||||
.insert(path.to_string(), options);
|
||||
}
|
||||
|
||||
let path = static_path(options, path);
|
||||
@@ -1322,8 +1326,11 @@ where
|
||||
.await;
|
||||
(owner.with(use_context::<ResponseOptions>), html)
|
||||
} else {
|
||||
let headers =
|
||||
STATIC_HEADERS.get(orig_path).map(|v| v.clone());
|
||||
let headers = STATIC_HEADERS
|
||||
.read()
|
||||
.or_poisoned()
|
||||
.get(orig_path)
|
||||
.cloned();
|
||||
(headers, None)
|
||||
};
|
||||
|
||||
|
||||
@@ -14,7 +14,6 @@ hydration_context = { workspace = true }
|
||||
axum = { default-features = false, features = [
|
||||
"matched-path",
|
||||
], workspace = true }
|
||||
dashmap = { workspace = true, default-features = true }
|
||||
futures = { workspace = true, default-features = true }
|
||||
leptos = { workspace = true, features = ["nonce", "ssr"] }
|
||||
server_fn = { workspace = true, features = ["axum-no-default"] }
|
||||
@@ -28,6 +27,7 @@ tokio = { default-features = false, workspace = true }
|
||||
tower = { features = ["util"], workspace = true, default-features = true }
|
||||
tower-http = { workspace = true, default-features = true }
|
||||
tracing = { optional = true, workspace = true, default-features = true }
|
||||
or_poisoned = { workspace = true, default-features = true }
|
||||
|
||||
[dev-dependencies]
|
||||
axum = { workspace = true, default-features = true }
|
||||
|
||||
@@ -47,8 +47,6 @@ use axum::{
|
||||
response::IntoResponse,
|
||||
routing::{delete, get, patch, post, put},
|
||||
};
|
||||
#[cfg(feature = "default")]
|
||||
use dashmap::DashMap;
|
||||
use futures::{stream::once, Future, Stream, StreamExt};
|
||||
use hydration_context::SsrSharedContext;
|
||||
use leptos::{
|
||||
@@ -69,12 +67,13 @@ use leptos_router::{
|
||||
static_routes::RegenerationFn, ExpandOptionals, PathSegment, RouteList,
|
||||
RouteListing, SsrMode,
|
||||
};
|
||||
use or_poisoned::OrPoisoned;
|
||||
use parking_lot::RwLock;
|
||||
use server_fn::{error::ServerFnErrorErr, redirect::REDIRECT_HEADER};
|
||||
#[cfg(feature = "default")]
|
||||
use std::path::Path;
|
||||
#[cfg(feature = "default")]
|
||||
use std::sync::LazyLock;
|
||||
#[cfg(feature = "default")]
|
||||
use std::{collections::HashMap, path::Path};
|
||||
use std::{collections::HashSet, fmt::Debug, io, pin::Pin, sync::Arc};
|
||||
#[cfg(feature = "default")]
|
||||
use tower::util::ServiceExt;
|
||||
@@ -1522,8 +1521,9 @@ impl StaticRouteGenerator {
|
||||
}
|
||||
|
||||
#[cfg(feature = "default")]
|
||||
static STATIC_HEADERS: LazyLock<DashMap<String, ResponseOptions>> =
|
||||
LazyLock::new(DashMap::new);
|
||||
static STATIC_HEADERS: LazyLock<
|
||||
std::sync::RwLock<HashMap<String, ResponseOptions>>,
|
||||
> = LazyLock::new(Default::default);
|
||||
|
||||
#[cfg(feature = "default")]
|
||||
fn was_404(owner: &Owner) -> bool {
|
||||
@@ -1558,7 +1558,10 @@ async fn write_static_route(
|
||||
html: &str,
|
||||
) -> Result<(), std::io::Error> {
|
||||
if let Some(options) = response_options {
|
||||
STATIC_HEADERS.insert(path.to_string(), options);
|
||||
STATIC_HEADERS
|
||||
.write()
|
||||
.or_poisoned()
|
||||
.insert(path.to_string(), options);
|
||||
}
|
||||
|
||||
let path = static_path(options, path);
|
||||
@@ -1635,7 +1638,11 @@ where
|
||||
.await;
|
||||
(owner.with(use_context::<ResponseOptions>), html)
|
||||
} else {
|
||||
let headers = STATIC_HEADERS.get(orig_path).map(|v| v.clone());
|
||||
let headers = STATIC_HEADERS
|
||||
.read()
|
||||
.or_poisoned()
|
||||
.get(orig_path)
|
||||
.map(|v| v.clone());
|
||||
(headers, None)
|
||||
};
|
||||
|
||||
|
||||
@@ -17,7 +17,6 @@ paste = { workspace = true, default-features = true }
|
||||
reactive_graph = { workspace = true }
|
||||
rustc-hash = { workspace = true, default-features = true }
|
||||
reactive_stores_macro = { workspace = true }
|
||||
dashmap = { workspace = true, default-features = true }
|
||||
send_wrapper = { workspace = true, default-features = true }
|
||||
|
||||
[dev-dependencies]
|
||||
|
||||
@@ -239,6 +239,7 @@
|
||||
//! field in the signal inner `Arc<RwLock<_>>`, and tracks the trigger that corresponds with its
|
||||
//! path; calling `.write()` returns a writeable guard, and notifies that same trigger.
|
||||
|
||||
use or_poisoned::OrPoisoned;
|
||||
use reactive_graph::{
|
||||
owner::{ArenaItem, LocalStorage, Storage, SyncStorage},
|
||||
signal::{
|
||||
@@ -414,32 +415,15 @@ impl<K> Default for FieldKeys<K> {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
type HashMap<K, V> = Arc<dashmap::DashMap<K, V>>;
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
type HashMap<K, V> = send_wrapper::SendWrapper<
|
||||
std::rc::Rc<std::cell::RefCell<std::collections::HashMap<K, V>>>,
|
||||
>;
|
||||
type Map<K, V> = Arc<std::sync::RwLock<std::collections::HashMap<K, V>>>;
|
||||
|
||||
/// A map of the keys for a keyed subfield.
|
||||
#[derive(Clone)]
|
||||
#[derive(Clone, Default)]
|
||||
pub struct KeyMap(
|
||||
HashMap<StorePath, Box<dyn Any + Send + Sync>>,
|
||||
HashMap<(StorePath, usize), StorePathSegment>,
|
||||
Map<StorePath, Box<dyn Any + Send + Sync>>,
|
||||
Map<(StorePath, usize), StorePathSegment>,
|
||||
);
|
||||
|
||||
impl Default for KeyMap {
|
||||
fn default() -> Self {
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
return Self(Default::default(), Default::default());
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
return Self(
|
||||
send_wrapper::SendWrapper::new(Default::default()),
|
||||
send_wrapper::SendWrapper::new(Default::default()),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
impl KeyMap {
|
||||
fn with_field_keys<K, T>(
|
||||
&self,
|
||||
@@ -452,62 +436,33 @@ impl KeyMap {
|
||||
{
|
||||
let initial_keys = initialize();
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
let mut entry = self
|
||||
.0
|
||||
let mut guard = self.0.write().or_poisoned();
|
||||
let entry = guard
|
||||
.entry(path.clone())
|
||||
.or_insert_with(|| Box::new(FieldKeys::new(initial_keys)));
|
||||
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
let entry = if !self.0.borrow().contains_key(&path) {
|
||||
Some(Box::new(FieldKeys::new(initial_keys)))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
let mut map = self.0.borrow_mut();
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
let entry = map.entry(path.clone()).or_insert_with(|| entry.unwrap());
|
||||
|
||||
let entry = entry.downcast_mut::<FieldKeys<K>>()?;
|
||||
let (result, new_keys) = fun(entry);
|
||||
if !new_keys.is_empty() {
|
||||
for (idx, segment) in new_keys {
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
self.1.insert((path.clone(), idx), segment);
|
||||
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
self.1.borrow_mut().insert((path.clone(), idx), segment);
|
||||
self.1
|
||||
.write()
|
||||
.or_poisoned()
|
||||
.insert((path.clone(), idx), segment);
|
||||
}
|
||||
}
|
||||
Some(result)
|
||||
}
|
||||
|
||||
fn contains_key(&self, key: &StorePath) -> bool {
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
{
|
||||
self.0.contains_key(key)
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
{
|
||||
self.0.borrow_mut().contains_key(key)
|
||||
}
|
||||
self.0.read().or_poisoned().contains_key(key)
|
||||
}
|
||||
|
||||
fn get_key_for_index(
|
||||
&self,
|
||||
key: &(StorePath, usize),
|
||||
) -> Option<StorePathSegment> {
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
{
|
||||
self.1.get(key).as_deref().copied()
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
{
|
||||
self.1.borrow().get(key).as_deref().copied()
|
||||
}
|
||||
self.1.read().or_poisoned().get(key).copied()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -25,10 +25,10 @@ send_wrapper = { features = [
|
||||
"futures",
|
||||
], optional = true, workspace = true, default-features = true }
|
||||
thiserror = { workspace = true, default-features = true }
|
||||
or_poisoned = { workspace = true, default-features = true }
|
||||
|
||||
# registration system
|
||||
inventory = { optional = true, workspace = true, default-features = true }
|
||||
dashmap = { workspace = true, default-features = true }
|
||||
|
||||
## servers
|
||||
# actix
|
||||
|
||||
@@ -145,7 +145,6 @@ use codec::{Encoding, FromReq, FromRes, IntoReq, IntoRes};
|
||||
pub use const_format;
|
||||
#[doc(hidden)]
|
||||
pub use const_str;
|
||||
use dashmap::DashMap;
|
||||
pub use error::ServerFnError;
|
||||
#[cfg(feature = "form-redirects")]
|
||||
use error::ServerFnUrlError;
|
||||
@@ -165,12 +164,13 @@ pub use serde;
|
||||
pub use serde_lite;
|
||||
use server::Server;
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
fmt::{Debug, Display},
|
||||
future::Future,
|
||||
marker::PhantomData,
|
||||
ops::{Deref, DerefMut},
|
||||
pin::Pin,
|
||||
sync::{Arc, LazyLock},
|
||||
sync::{Arc, LazyLock, RwLock},
|
||||
};
|
||||
#[doc(hidden)]
|
||||
pub use xxhash_rust;
|
||||
@@ -866,12 +866,14 @@ pub use inventory;
|
||||
macro_rules! initialize_server_fn_map {
|
||||
($req:ty, $res:ty) => {
|
||||
std::sync::LazyLock::new(|| {
|
||||
$crate::inventory::iter::<ServerFnTraitObj<$req, $res>>
|
||||
.into_iter()
|
||||
.map(|obj| {
|
||||
((obj.path().to_string(), obj.method()), obj.clone())
|
||||
})
|
||||
.collect()
|
||||
std::sync::RwLock::new(
|
||||
$crate::inventory::iter::<ServerFnTraitObj<$req, $res>>
|
||||
.into_iter()
|
||||
.map(|obj| {
|
||||
((obj.path().to_string(), obj.method()), obj.clone())
|
||||
})
|
||||
.collect(),
|
||||
)
|
||||
})
|
||||
};
|
||||
}
|
||||
@@ -984,7 +986,7 @@ impl<Req, Res> Clone for ServerFnTraitObj<Req, Res> {
|
||||
|
||||
#[allow(unused)] // used by server integrations
|
||||
type LazyServerFnMap<Req, Res> =
|
||||
LazyLock<DashMap<(String, Method), ServerFnTraitObj<Req, Res>>>;
|
||||
LazyLock<RwLock<HashMap<(String, Method), ServerFnTraitObj<Req, Res>>>>;
|
||||
|
||||
#[cfg(feature = "ssr")]
|
||||
impl<Req: 'static, Res: 'static> inventory::Collect
|
||||
@@ -1006,6 +1008,7 @@ pub mod axum {
|
||||
};
|
||||
use axum::body::Body;
|
||||
use http::{Method, Request, Response, StatusCode};
|
||||
use or_poisoned::OrPoisoned;
|
||||
use std::future::Future;
|
||||
|
||||
static REGISTERED_SERVER_FUNCTIONS: LazyServerFnMap<
|
||||
@@ -1066,7 +1069,7 @@ pub mod axum {
|
||||
>,
|
||||
> + 'static,
|
||||
{
|
||||
REGISTERED_SERVER_FUNCTIONS.insert(
|
||||
REGISTERED_SERVER_FUNCTIONS.write().or_poisoned().insert(
|
||||
(T::PATH.into(), T::Protocol::METHOD),
|
||||
ServerFnTraitObj::new::<T>(|req| Box::pin(T::run_on_server(req))),
|
||||
);
|
||||
@@ -1074,9 +1077,14 @@ pub mod axum {
|
||||
|
||||
/// The set of all registered server function paths.
|
||||
pub fn server_fn_paths() -> impl Iterator<Item = (&'static str, Method)> {
|
||||
REGISTERED_SERVER_FUNCTIONS
|
||||
.iter()
|
||||
let paths: Vec<_> = REGISTERED_SERVER_FUNCTIONS
|
||||
.read()
|
||||
.unwrap()
|
||||
.values()
|
||||
.map(|item| (item.path(), item.method()))
|
||||
.collect();
|
||||
|
||||
paths.into_iter()
|
||||
}
|
||||
|
||||
/// An Axum handler that responds to a server function request.
|
||||
@@ -1110,14 +1118,18 @@ pub mod axum {
|
||||
method: Method,
|
||||
) -> Option<BoxedService<Request<Body>, Response<Body>>> {
|
||||
let key = (path.into(), method);
|
||||
REGISTERED_SERVER_FUNCTIONS.get(&key).map(|server_fn| {
|
||||
let middleware = (server_fn.middleware)();
|
||||
let mut service = server_fn.clone().boxed();
|
||||
for middleware in middleware {
|
||||
service = middleware.layer(service);
|
||||
}
|
||||
service
|
||||
})
|
||||
REGISTERED_SERVER_FUNCTIONS
|
||||
.read()
|
||||
.or_poisoned()
|
||||
.get(&key)
|
||||
.map(|server_fn| {
|
||||
let middleware = (server_fn.middleware)();
|
||||
let mut service = server_fn.clone().boxed();
|
||||
for middleware in middleware {
|
||||
service = middleware.layer(service);
|
||||
}
|
||||
service
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1131,6 +1143,7 @@ pub mod actix {
|
||||
};
|
||||
use actix_web::{web::Payload, HttpRequest, HttpResponse};
|
||||
use http::Method;
|
||||
use or_poisoned::OrPoisoned;
|
||||
#[doc(hidden)]
|
||||
pub use send_wrapper::SendWrapper;
|
||||
use std::future::Future;
|
||||
@@ -1177,7 +1190,7 @@ pub mod actix {
|
||||
>,
|
||||
> + 'static,
|
||||
{
|
||||
REGISTERED_SERVER_FUNCTIONS.insert(
|
||||
REGISTERED_SERVER_FUNCTIONS.write().or_poisoned().insert(
|
||||
(T::PATH.into(), T::Protocol::METHOD),
|
||||
ServerFnTraitObj::new::<T>(|req| Box::pin(T::run_on_server(req))),
|
||||
);
|
||||
@@ -1185,9 +1198,14 @@ pub mod actix {
|
||||
|
||||
/// The set of all registered server function paths.
|
||||
pub fn server_fn_paths() -> impl Iterator<Item = (&'static str, Method)> {
|
||||
REGISTERED_SERVER_FUNCTIONS
|
||||
.iter()
|
||||
let paths: Vec<_> = REGISTERED_SERVER_FUNCTIONS
|
||||
.read()
|
||||
.unwrap()
|
||||
.values()
|
||||
.map(|item| (item.path(), item.method()))
|
||||
.collect();
|
||||
|
||||
paths.into_iter()
|
||||
}
|
||||
|
||||
/// An Actix handler that responds to a server function request.
|
||||
@@ -1236,16 +1254,18 @@ pub mod actix {
|
||||
ActixMethod::CONNECT => Method::CONNECT,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
REGISTERED_SERVER_FUNCTIONS.get(&(path.into(), method)).map(
|
||||
|server_fn| {
|
||||
REGISTERED_SERVER_FUNCTIONS
|
||||
.read()
|
||||
.or_poisoned()
|
||||
.get(&(path.into(), method))
|
||||
.map(|server_fn| {
|
||||
let middleware = (server_fn.middleware)();
|
||||
let mut service = server_fn.clone().boxed();
|
||||
for middleware in middleware {
|
||||
service = middleware.layer(service);
|
||||
}
|
||||
service
|
||||
},
|
||||
)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user