Merge pull request #1106 from Demonthos/make-registering-server-fn-optional
Make registering server functions optional
This commit is contained in:
17 files changed
+107
-80
No files matched your search
@@ -16,9 +16,6 @@ fn main() {
|
|||||||
use axum::extract::State;
|
use axum::extract::State;
|
||||||
use axum::routing::get;
|
use axum::routing::get;
|
||||||
|
|
||||||
// Register the server function before starting the server
|
|
||||||
DoubleServer::register().unwrap();
|
|
||||||
|
|
||||||
tokio::runtime::Runtime::new()
|
tokio::runtime::Runtime::new()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.block_on(async move {
|
.block_on(async move {
|
||||||
|
|||||||
@@ -25,9 +25,6 @@ fn main() {
|
|||||||
use axum::routing::get;
|
use axum::routing::get;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
// Register the server function before starting the server
|
|
||||||
DoubleServer::register().unwrap();
|
|
||||||
|
|
||||||
tokio::runtime::Runtime::new()
|
tokio::runtime::Runtime::new()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.block_on(async move {
|
.block_on(async move {
|
||||||
|
|||||||
@@ -16,9 +16,6 @@ fn main() {
|
|||||||
use axum::extract::State;
|
use axum::extract::State;
|
||||||
use axum::routing::get;
|
use axum::routing::get;
|
||||||
|
|
||||||
// Register the server function before starting the server
|
|
||||||
DoubleServer::register().unwrap();
|
|
||||||
|
|
||||||
tokio::runtime::Runtime::new()
|
tokio::runtime::Runtime::new()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.block_on(async move {
|
.block_on(async move {
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ keywords = ["dom", "ui", "gui", "react", "ssr", "fullstack"]
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
# server functions
|
# server functions
|
||||||
server_fn = { git = "https://github.com/leptos-rs/leptos", rev = "671b1e4a8fff7a2e05bb621ef08e87be2b18ccae", default-features = false, features = ["stable"] }
|
server_fn = { git = "https://github.com/leptos-rs/leptos", rev = "15a4e54435eb5a539afb75891292bcccd2cc8e85", default-features = false, features = ["stable"] }
|
||||||
dioxus_server_macro = { path = "server-macro" }
|
dioxus_server_macro = { path = "server-macro" }
|
||||||
|
|
||||||
# warp
|
# warp
|
||||||
|
|||||||
@@ -46,7 +46,6 @@ fn main() {
|
|||||||
);
|
);
|
||||||
#[cfg(feature = "ssr")]
|
#[cfg(feature = "ssr")]
|
||||||
{
|
{
|
||||||
GetMeaning::register().unwrap();
|
|
||||||
tokio::runtime::Runtime::new()
|
tokio::runtime::Runtime::new()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.block_on(async move {
|
.block_on(async move {
|
||||||
|
|||||||
@@ -8,9 +8,6 @@ use dioxus_fullstack::prelude::*;
|
|||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() {
|
async fn main() {
|
||||||
PostServerData::register().unwrap();
|
|
||||||
GetServerData::register().unwrap();
|
|
||||||
|
|
||||||
let addr = std::net::SocketAddr::from(([127, 0, 0, 1], 8080));
|
let addr = std::net::SocketAddr::from(([127, 0, 0, 1], 8080));
|
||||||
axum::Server::bind(&addr)
|
axum::Server::bind(&addr)
|
||||||
.serve(
|
.serve(
|
||||||
|
|||||||
@@ -32,8 +32,6 @@ fn main() {
|
|||||||
true
|
true
|
||||||
}));
|
}));
|
||||||
|
|
||||||
PostServerData::register().unwrap();
|
|
||||||
GetServerData::register().unwrap();
|
|
||||||
tokio::runtime::Runtime::new()
|
tokio::runtime::Runtime::new()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.block_on(async move {
|
.block_on(async move {
|
||||||
|
|||||||
@@ -34,8 +34,6 @@ fn main() {
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
use axum::extract::State;
|
use axum::extract::State;
|
||||||
PostServerData::register().unwrap();
|
|
||||||
GetServerData::register().unwrap();
|
|
||||||
tokio::runtime::Runtime::new()
|
tokio::runtime::Runtime::new()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.block_on(async move {
|
.block_on(async move {
|
||||||
|
|||||||
@@ -33,8 +33,6 @@ fn main() {
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
use salvo::prelude::*;
|
use salvo::prelude::*;
|
||||||
PostServerData::register().unwrap();
|
|
||||||
GetServerData::register().unwrap();
|
|
||||||
tokio::runtime::Runtime::new()
|
tokio::runtime::Runtime::new()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.block_on(async move {
|
.block_on(async move {
|
||||||
|
|||||||
@@ -32,8 +32,6 @@ fn main() {
|
|||||||
true
|
true
|
||||||
}));
|
}));
|
||||||
|
|
||||||
PostServerData::register().unwrap();
|
|
||||||
GetServerData::register().unwrap();
|
|
||||||
tokio::runtime::Runtime::new()
|
tokio::runtime::Runtime::new()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.block_on(async move {
|
.block_on(async move {
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ edition = "2021"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
quote = "1.0.26"
|
quote = "1.0.26"
|
||||||
server_fn_macro = { git = "https://github.com/leptos-rs/leptos", rev = "671b1e4a8fff7a2e05bb621ef08e87be2b18ccae", features = ["stable"] }
|
server_fn_macro = { git = "https://github.com/leptos-rs/leptos", rev = "15a4e54435eb5a539afb75891292bcccd2cc8e85", features = ["stable"] }
|
||||||
syn = { version = "1", features = ["full"] }
|
syn = { version = "2", features = ["full"] }
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
proc-macro = true
|
proc-macro = true
|
||||||
@@ -35,7 +35,6 @@ use server_fn_macro::*;
|
|||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// Note the following:
|
/// Note the following:
|
||||||
/// - You must **register** the server function by calling `T::register()` somewhere in your main function.
|
|
||||||
/// - **Server functions must be `async`.** Even if the work being done inside the function body
|
/// - **Server functions must be `async`.** Even if the work being done inside the function body
|
||||||
/// can run synchronously on the server, from the client’s perspective it involves an asynchronous
|
/// can run synchronously on the server, from the client’s perspective it involves an asynchronous
|
||||||
/// function call.
|
/// function call.
|
||||||
@@ -62,6 +61,7 @@ pub fn server(args: proc_macro::TokenStream, s: TokenStream) -> TokenStream {
|
|||||||
match server_macro_impl(
|
match server_macro_impl(
|
||||||
args.into(),
|
args.into(),
|
||||||
s.into(),
|
s.into(),
|
||||||
|
syn::parse_quote!(::dioxus_fullstack::prelude::ServerFnTraitObj),
|
||||||
Some(context),
|
Some(context),
|
||||||
Some(syn::parse_quote!(::dioxus_fullstack::prelude::server_fn)),
|
Some(syn::parse_quote!(::dioxus_fullstack::prelude::server_fn)),
|
||||||
) {
|
) {
|
||||||
|
|||||||
@@ -12,7 +12,6 @@
|
|||||||
//! dioxus_web::launch_cfg(app, dioxus_web::Config::new().hydrate(true));
|
//! dioxus_web::launch_cfg(app, dioxus_web::Config::new().hydrate(true));
|
||||||
//! #[cfg(feature = "ssr")]
|
//! #[cfg(feature = "ssr")]
|
||||||
//! {
|
//! {
|
||||||
//! GetServerData::register().unwrap();
|
|
||||||
//! tokio::runtime::Runtime::new()
|
//! tokio::runtime::Runtime::new()
|
||||||
//! .unwrap()
|
//! .unwrap()
|
||||||
//! .block_on(async move {
|
//! .block_on(async move {
|
||||||
@@ -107,7 +106,7 @@ pub trait DioxusRouterExt<S> {
|
|||||||
fn register_server_fns_with_handler<H, T>(
|
fn register_server_fns_with_handler<H, T>(
|
||||||
self,
|
self,
|
||||||
server_fn_route: &'static str,
|
server_fn_route: &'static str,
|
||||||
handler: impl Fn(ServerFunction) -> H,
|
handler: impl FnMut(server_fn::ServerFnTraitObj<DioxusServerContext>) -> H,
|
||||||
) -> Self
|
) -> Self
|
||||||
where
|
where
|
||||||
H: Handler<T, S>,
|
H: Handler<T, S>,
|
||||||
@@ -232,7 +231,7 @@ where
|
|||||||
fn register_server_fns_with_handler<H, T>(
|
fn register_server_fns_with_handler<H, T>(
|
||||||
self,
|
self,
|
||||||
server_fn_route: &'static str,
|
server_fn_route: &'static str,
|
||||||
mut handler: impl FnMut(ServerFunction) -> H,
|
mut handler: impl FnMut(server_fn::ServerFnTraitObj<DioxusServerContext>) -> H,
|
||||||
) -> Self
|
) -> Self
|
||||||
where
|
where
|
||||||
H: Handler<T, S, Body>,
|
H: Handler<T, S, Body>,
|
||||||
@@ -243,7 +242,7 @@ where
|
|||||||
for server_fn_path in DioxusServerFnRegistry::paths_registered() {
|
for server_fn_path in DioxusServerFnRegistry::paths_registered() {
|
||||||
let func = DioxusServerFnRegistry::get(server_fn_path).unwrap();
|
let func = DioxusServerFnRegistry::get(server_fn_path).unwrap();
|
||||||
let full_route = format!("{server_fn_route}/{server_fn_path}");
|
let full_route = format!("{server_fn_route}/{server_fn_path}");
|
||||||
match func.encoding {
|
match func.encoding() {
|
||||||
Encoding::Url | Encoding::Cbor => {
|
Encoding::Url | Encoding::Cbor => {
|
||||||
router = router.route(&full_route, post(handler(func)));
|
router = router.route(&full_route, post(handler(func)));
|
||||||
}
|
}
|
||||||
@@ -314,7 +313,7 @@ where
|
|||||||
let cfg = cfg.into();
|
let cfg = cfg.into();
|
||||||
|
|
||||||
// Add server functions and render index.html
|
// Add server functions and render index.html
|
||||||
self.serve_static_assets(&cfg.assets_path)
|
self.serve_static_assets(cfg.assets_path)
|
||||||
.route(
|
.route(
|
||||||
"/",
|
"/",
|
||||||
get(render_handler).with_state((cfg, SSRState::default())),
|
get(render_handler).with_state((cfg, SSRState::default())),
|
||||||
@@ -371,7 +370,7 @@ async fn render_handler<P: Clone + serde::Serialize + Send + Sync + 'static>(
|
|||||||
/// A default handler for server functions. It will deserialize the request, call the server function, and serialize the response.
|
/// A default handler for server functions. It will deserialize the request, call the server function, and serialize the response.
|
||||||
pub async fn server_fn_handler(
|
pub async fn server_fn_handler(
|
||||||
server_context: DioxusServerContext,
|
server_context: DioxusServerContext,
|
||||||
function: ServerFunction,
|
function: server_fn::ServerFnTraitObj<DioxusServerContext>,
|
||||||
parts: Arc<RequestParts>,
|
parts: Arc<RequestParts>,
|
||||||
body: Body,
|
body: Body,
|
||||||
) -> impl IntoResponse {
|
) -> impl IntoResponse {
|
||||||
@@ -389,11 +388,11 @@ pub async fn server_fn_handler(
|
|||||||
.expect("couldn't spawn runtime")
|
.expect("couldn't spawn runtime")
|
||||||
.block_on(async {
|
.block_on(async {
|
||||||
let query = &query_string.into();
|
let query = &query_string.into();
|
||||||
let data = match &function.encoding {
|
let data = match &function.encoding() {
|
||||||
Encoding::Url | Encoding::Cbor => &body,
|
Encoding::Url | Encoding::Cbor => &body,
|
||||||
Encoding::GetJSON | Encoding::GetCBOR => query,
|
Encoding::GetJSON | Encoding::GetCBOR => query,
|
||||||
};
|
};
|
||||||
let resp = match (function.trait_obj)(server_context.clone(), &data).await {
|
let resp = match function.call(server_context.clone(), data).await {
|
||||||
Ok(serialized) => {
|
Ok(serialized) => {
|
||||||
// if this is Accept: application/json then send a serialized JSON response
|
// if this is Accept: application/json then send a serialized JSON response
|
||||||
let accept_header = parts
|
let accept_header = parts
|
||||||
|
|||||||
@@ -12,7 +12,6 @@
|
|||||||
//! #[cfg(feature = "ssr")]
|
//! #[cfg(feature = "ssr")]
|
||||||
//! {
|
//! {
|
||||||
//! use salvo::prelude::*;
|
//! use salvo::prelude::*;
|
||||||
//! GetServerData::register().unwrap();
|
|
||||||
//! tokio::runtime::Runtime::new()
|
//! tokio::runtime::Runtime::new()
|
||||||
//! .unwrap()
|
//! .unwrap()
|
||||||
//! .block_on(async move {
|
//! .block_on(async move {
|
||||||
@@ -77,7 +76,7 @@ pub trait DioxusRouterExt {
|
|||||||
/// use dioxus_fullstack::prelude::*;
|
/// use dioxus_fullstack::prelude::*;
|
||||||
///
|
///
|
||||||
/// struct ServerFunctionHandler {
|
/// struct ServerFunctionHandler {
|
||||||
/// server_fn: ServerFunction,
|
/// server_fn: server_fn::ServerFnTraitObj<DioxusServerContext>,
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// #[handler]
|
/// #[handler]
|
||||||
@@ -110,7 +109,7 @@ pub trait DioxusRouterExt {
|
|||||||
fn register_server_fns_with_handler<H>(
|
fn register_server_fns_with_handler<H>(
|
||||||
self,
|
self,
|
||||||
server_fn_route: &'static str,
|
server_fn_route: &'static str,
|
||||||
handler: impl Fn(ServerFunction) -> H,
|
handler: impl Fn(server_fn::ServerFnTraitObj<DioxusServerContext>) -> H,
|
||||||
) -> Self
|
) -> Self
|
||||||
where
|
where
|
||||||
H: Handler + 'static;
|
H: Handler + 'static;
|
||||||
@@ -204,7 +203,7 @@ impl DioxusRouterExt for Router {
|
|||||||
fn register_server_fns_with_handler<H>(
|
fn register_server_fns_with_handler<H>(
|
||||||
self,
|
self,
|
||||||
server_fn_route: &'static str,
|
server_fn_route: &'static str,
|
||||||
mut handler: impl FnMut(ServerFunction) -> H,
|
mut handler: impl FnMut(server_fn::ServerFnTraitObj<DioxusServerContext>) -> H,
|
||||||
) -> Self
|
) -> Self
|
||||||
where
|
where
|
||||||
H: Handler + 'static,
|
H: Handler + 'static,
|
||||||
@@ -213,7 +212,7 @@ impl DioxusRouterExt for Router {
|
|||||||
for server_fn_path in DioxusServerFnRegistry::paths_registered() {
|
for server_fn_path in DioxusServerFnRegistry::paths_registered() {
|
||||||
let func = DioxusServerFnRegistry::get(server_fn_path).unwrap();
|
let func = DioxusServerFnRegistry::get(server_fn_path).unwrap();
|
||||||
let full_route = format!("{server_fn_route}/{server_fn_path}");
|
let full_route = format!("{server_fn_route}/{server_fn_path}");
|
||||||
match func.encoding {
|
match func.encoding() {
|
||||||
Encoding::Url | Encoding::Cbor => {
|
Encoding::Url | Encoding::Cbor => {
|
||||||
router = router.push(Router::with_path(&full_route).post(handler(func)));
|
router = router.push(Router::with_path(&full_route).post(handler(func)));
|
||||||
}
|
}
|
||||||
@@ -280,7 +279,7 @@ impl DioxusRouterExt for Router {
|
|||||||
) -> Self {
|
) -> Self {
|
||||||
let cfg = cfg.into();
|
let cfg = cfg.into();
|
||||||
|
|
||||||
self.serve_static_assets(&cfg.assets_path)
|
self.serve_static_assets(cfg.assets_path)
|
||||||
.connect_hot_reload()
|
.connect_hot_reload()
|
||||||
.register_server_fns(server_fn_path)
|
.register_server_fns(server_fn_path)
|
||||||
.push(Router::with_path("/").get(SSRHandler { cfg }))
|
.push(Router::with_path("/").get(SSRHandler { cfg }))
|
||||||
@@ -288,8 +287,8 @@ impl DioxusRouterExt for Router {
|
|||||||
|
|
||||||
fn connect_hot_reload(self) -> Self {
|
fn connect_hot_reload(self) -> Self {
|
||||||
let mut _dioxus_router = Router::with_path("_dioxus");
|
let mut _dioxus_router = Router::with_path("_dioxus");
|
||||||
_dioxus_router = _dioxus_router
|
_dioxus_router =
|
||||||
.push(Router::with_path("hot_reload").handle(HotReloadHandler::default()));
|
_dioxus_router.push(Router::with_path("hot_reload").handle(HotReloadHandler));
|
||||||
#[cfg(all(debug_assertions, feature = "hot-reload", feature = "ssr"))]
|
#[cfg(all(debug_assertions, feature = "hot-reload", feature = "ssr"))]
|
||||||
{
|
{
|
||||||
_dioxus_router = _dioxus_router.push(Router::with_path("disconnect").handle(ignore_ws));
|
_dioxus_router = _dioxus_router.push(Router::with_path("disconnect").handle(ignore_ws));
|
||||||
@@ -346,12 +345,15 @@ impl<P: Clone + serde::Serialize + Send + Sync + 'static> Handler for SSRHandler
|
|||||||
/// A default handler for server functions. It will deserialize the request body, call the server function, and serialize the response.
|
/// A default handler for server functions. It will deserialize the request body, call the server function, and serialize the response.
|
||||||
pub struct ServerFnHandler {
|
pub struct ServerFnHandler {
|
||||||
server_context: DioxusServerContext,
|
server_context: DioxusServerContext,
|
||||||
function: ServerFunction,
|
function: server_fn::ServerFnTraitObj<DioxusServerContext>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ServerFnHandler {
|
impl ServerFnHandler {
|
||||||
/// Create a new server function handler with the given server context and server function.
|
/// Create a new server function handler with the given server context and server function.
|
||||||
pub fn new(server_context: impl Into<DioxusServerContext>, function: ServerFunction) -> Self {
|
pub fn new(
|
||||||
|
server_context: impl Into<DioxusServerContext>,
|
||||||
|
function: server_fn::ServerFnTraitObj<DioxusServerContext>,
|
||||||
|
) -> Self {
|
||||||
let server_context = server_context.into();
|
let server_context = server_context.into();
|
||||||
Self {
|
Self {
|
||||||
server_context,
|
server_context,
|
||||||
@@ -395,11 +397,11 @@ impl ServerFnHandler {
|
|||||||
tokio::runtime::Runtime::new()
|
tokio::runtime::Runtime::new()
|
||||||
.expect("couldn't spawn runtime")
|
.expect("couldn't spawn runtime")
|
||||||
.block_on(async move {
|
.block_on(async move {
|
||||||
let data = match &function.encoding {
|
let data = match function.encoding() {
|
||||||
Encoding::Url | Encoding::Cbor => &body,
|
Encoding::Url | Encoding::Cbor => &body,
|
||||||
Encoding::GetJSON | Encoding::GetCBOR => &query,
|
Encoding::GetJSON | Encoding::GetCBOR => &query,
|
||||||
};
|
};
|
||||||
let resp = (function.trait_obj)(server_context, data).await;
|
let resp = function.call(server_context, data).await;
|
||||||
|
|
||||||
resp_tx.send(resp).unwrap();
|
resp_tx.send(resp).unwrap();
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -11,7 +11,6 @@
|
|||||||
//! dioxus_web::launch_cfg(app, dioxus_web::Config::new().hydrate(true));
|
//! dioxus_web::launch_cfg(app, dioxus_web::Config::new().hydrate(true));
|
||||||
//! #[cfg(feature = "ssr")]
|
//! #[cfg(feature = "ssr")]
|
||||||
//! {
|
//! {
|
||||||
//! GetServerData::register().unwrap();
|
|
||||||
//! tokio::runtime::Runtime::new()
|
//! tokio::runtime::Runtime::new()
|
||||||
//! .unwrap()
|
//! .unwrap()
|
||||||
//! .block_on(async move {
|
//! .block_on(async move {
|
||||||
@@ -93,7 +92,7 @@ pub fn register_server_fns_with_handler<H, F, R>(
|
|||||||
mut handler: H,
|
mut handler: H,
|
||||||
) -> BoxedFilter<(R,)>
|
) -> BoxedFilter<(R,)>
|
||||||
where
|
where
|
||||||
H: FnMut(String, ServerFunction) -> F,
|
H: FnMut(String, server_fn::ServerFnTraitObj<DioxusServerContext>) -> F,
|
||||||
F: Filter<Extract = (R,), Error = warp::Rejection> + Send + Sync + 'static,
|
F: Filter<Extract = (R,), Error = warp::Rejection> + Send + Sync + 'static,
|
||||||
F::Extract: Send,
|
F::Extract: Send,
|
||||||
R: Reply + 'static,
|
R: Reply + 'static,
|
||||||
@@ -104,7 +103,7 @@ where
|
|||||||
let full_route = format!("{server_fn_route}/{server_fn_path}")
|
let full_route = format!("{server_fn_route}/{server_fn_path}")
|
||||||
.trim_start_matches('/')
|
.trim_start_matches('/')
|
||||||
.to_string();
|
.to_string();
|
||||||
let route = handler(full_route, func.clone()).boxed();
|
let route = handler(full_route, func).boxed();
|
||||||
if let Some(boxed_filter) = filter.take() {
|
if let Some(boxed_filter) = filter.take() {
|
||||||
filter = Some(boxed_filter.or(route).unify().boxed());
|
filter = Some(boxed_filter.or(route).unify().boxed());
|
||||||
} else {
|
} else {
|
||||||
@@ -128,7 +127,7 @@ where
|
|||||||
/// ```
|
/// ```
|
||||||
pub fn register_server_fns(server_fn_route: &'static str) -> BoxedFilter<(impl Reply,)> {
|
pub fn register_server_fns(server_fn_route: &'static str) -> BoxedFilter<(impl Reply,)> {
|
||||||
register_server_fns_with_handler(server_fn_route, |full_route, func| {
|
register_server_fns_with_handler(server_fn_route, |full_route, func| {
|
||||||
path(full_route.clone())
|
path(full_route)
|
||||||
.and(warp::post().or(warp::get()).unify())
|
.and(warp::post().or(warp::get()).unify())
|
||||||
.and(request_parts())
|
.and(request_parts())
|
||||||
.and(warp::body::bytes())
|
.and(warp::body::bytes())
|
||||||
@@ -250,7 +249,7 @@ impl warp::reject::Reject for RecieveFailed {}
|
|||||||
/// A default handler for server functions. It will deserialize the request body, call the server function, and serialize the response.
|
/// A default handler for server functions. It will deserialize the request body, call the server function, and serialize the response.
|
||||||
pub async fn server_fn_handler(
|
pub async fn server_fn_handler(
|
||||||
server_context: impl Into<DioxusServerContext>,
|
server_context: impl Into<DioxusServerContext>,
|
||||||
function: ServerFunction,
|
function: server_fn::ServerFnTraitObj<DioxusServerContext>,
|
||||||
parts: RequestParts,
|
parts: RequestParts,
|
||||||
body: Bytes,
|
body: Bytes,
|
||||||
) -> Result<Box<dyn warp::Reply>, warp::Rejection> {
|
) -> Result<Box<dyn warp::Reply>, warp::Rejection> {
|
||||||
@@ -274,11 +273,11 @@ pub async fn server_fn_handler(
|
|||||||
.as_bytes()
|
.as_bytes()
|
||||||
.to_vec()
|
.to_vec()
|
||||||
.into();
|
.into();
|
||||||
let data = match &function.encoding {
|
let data = match function.encoding() {
|
||||||
Encoding::Url | Encoding::Cbor => &body,
|
Encoding::Url | Encoding::Cbor => &body,
|
||||||
Encoding::GetJSON | Encoding::GetCBOR => &query,
|
Encoding::GetJSON | Encoding::GetCBOR => &query,
|
||||||
};
|
};
|
||||||
let resp = match (function.trait_obj)(server_context.clone(), data).await {
|
let resp = match function.call(server_context.clone(), data).await {
|
||||||
Ok(serialized) => {
|
Ok(serialized) => {
|
||||||
// if this is Accept: application/json then send a serialized JSON response
|
// if this is Accept: application/json then send a serialized JSON response
|
||||||
let accept_header = parts
|
let accept_header = parts
|
||||||
@@ -373,7 +372,7 @@ pub fn connect_hot_reload() -> impl Filter<Extract = (impl Reply,), Error = warp
|
|||||||
use warp::ws::Message;
|
use warp::ws::Message;
|
||||||
|
|
||||||
let hot_reload = warp::path!("_dioxus" / "hot_reload")
|
let hot_reload = warp::path!("_dioxus" / "hot_reload")
|
||||||
.and(warp::any().then(|| crate::hot_reload::spawn_hot_reload()))
|
.and(warp::any().then(crate::hot_reload::spawn_hot_reload))
|
||||||
.and(warp::ws())
|
.and(warp::ws())
|
||||||
.map(move |state: &'static HotReloadState, ws: warp::ws::Ws| {
|
.map(move |state: &'static HotReloadState, ws: warp::ws::Ws| {
|
||||||
#[cfg(all(debug_assertions, feature = "hot-reload", feature = "ssr"))]
|
#[cfg(all(debug_assertions, feature = "hot-reload", feature = "ssr"))]
|
||||||
@@ -425,7 +424,7 @@ pub fn connect_hot_reload() -> impl Filter<Extract = (impl Reply,), Error = warp
|
|||||||
struct DisconnectOnDrop(Option<warp::ws::WebSocket>);
|
struct DisconnectOnDrop(Option<warp::ws::WebSocket>);
|
||||||
impl Drop for DisconnectOnDrop {
|
impl Drop for DisconnectOnDrop {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
let _ = self.0.take().unwrap().close();
|
std::mem::drop(self.0.take().unwrap().close());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ pub mod prelude {
|
|||||||
#[cfg(feature = "ssr")]
|
#[cfg(feature = "ssr")]
|
||||||
pub use crate::server_context::RequestParts;
|
pub use crate::server_context::RequestParts;
|
||||||
pub use crate::server_context::{DioxusServerContext, HasServerContext};
|
pub use crate::server_context::{DioxusServerContext, HasServerContext};
|
||||||
pub use crate::server_fn::ServerFn;
|
pub use crate::server_fn::DioxusServerFn;
|
||||||
#[cfg(feature = "ssr")]
|
#[cfg(feature = "ssr")]
|
||||||
pub use crate::server_fn::{ServerFnTraitObj, ServerFunction};
|
pub use crate::server_fn::{ServerFnTraitObj, ServerFunction};
|
||||||
pub use dioxus_server_macro::*;
|
pub use dioxus_server_macro::*;
|
||||||
|
|||||||
@@ -1,30 +1,76 @@
|
|||||||
use crate::server_context::DioxusServerContext;
|
use crate::server_context::DioxusServerContext;
|
||||||
|
|
||||||
#[cfg(any(feature = "ssr", doc))]
|
#[cfg(any(feature = "ssr", doc))]
|
||||||
|
#[derive(Clone)]
|
||||||
/// A trait object for a function that be called on serializable arguments and returns a serializable result.
|
/// A trait object for a function that be called on serializable arguments and returns a serializable result.
|
||||||
pub type ServerFnTraitObj = server_fn::ServerFnTraitObj<DioxusServerContext>;
|
pub struct ServerFnTraitObj(server_fn::ServerFnTraitObj<DioxusServerContext>);
|
||||||
|
|
||||||
|
#[cfg(any(feature = "ssr", doc))]
|
||||||
|
impl std::ops::Deref for ServerFnTraitObj {
|
||||||
|
type Target = server_fn::ServerFnTraitObj<DioxusServerContext>;
|
||||||
|
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
&self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(any(feature = "ssr", doc))]
|
||||||
|
impl std::ops::DerefMut for ServerFnTraitObj {
|
||||||
|
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||||
|
&mut self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(any(feature = "ssr", doc))]
|
||||||
|
impl ServerFnTraitObj {
|
||||||
|
fn new(
|
||||||
|
prefix: &'static str,
|
||||||
|
url: &'static str,
|
||||||
|
encoding: server_fn::Encoding,
|
||||||
|
run: ServerFunction,
|
||||||
|
) -> Self {
|
||||||
|
Self(server_fn::ServerFnTraitObj::new(prefix, url, encoding, run))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create a new `ServerFnTraitObj` from a `server_fn::ServerFnTraitObj`.
|
||||||
|
pub const fn from_generic_server_fn(
|
||||||
|
server_fn: server_fn::ServerFnTraitObj<DioxusServerContext>,
|
||||||
|
) -> Self {
|
||||||
|
Self(server_fn)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(any(feature = "ssr", doc))]
|
||||||
|
server_fn::inventory::collect!(ServerFnTraitObj);
|
||||||
|
|
||||||
#[cfg(any(feature = "ssr", doc))]
|
#[cfg(any(feature = "ssr", doc))]
|
||||||
/// A server function that can be called on serializable arguments and returns a serializable result.
|
/// A server function that can be called on serializable arguments and returns a serializable result.
|
||||||
pub type ServerFunction = server_fn::ServerFunction<DioxusServerContext>;
|
pub type ServerFunction = server_fn::SerializedFnTraitObj<DioxusServerContext>;
|
||||||
|
|
||||||
#[cfg(any(feature = "ssr", doc))]
|
#[cfg(any(feature = "ssr", doc))]
|
||||||
#[allow(clippy::type_complexity)]
|
#[allow(clippy::type_complexity)]
|
||||||
static REGISTERED_SERVER_FUNCTIONS: once_cell::sync::Lazy<
|
static REGISTERED_SERVER_FUNCTIONS: once_cell::sync::Lazy<
|
||||||
std::sync::Arc<std::sync::RwLock<std::collections::HashMap<&'static str, ServerFunction>>>,
|
std::sync::Arc<std::sync::RwLock<std::collections::HashMap<&'static str, ServerFnTraitObj>>>,
|
||||||
> = once_cell::sync::Lazy::new(Default::default);
|
> = once_cell::sync::Lazy::new(|| {
|
||||||
|
let mut map = std::collections::HashMap::new();
|
||||||
|
for server_fn in server_fn::inventory::iter::<ServerFnTraitObj> {
|
||||||
|
map.insert(server_fn.0.url(), server_fn.clone());
|
||||||
|
}
|
||||||
|
std::sync::Arc::new(std::sync::RwLock::new(map))
|
||||||
|
});
|
||||||
|
|
||||||
#[cfg(any(feature = "ssr", doc))]
|
#[cfg(any(feature = "ssr", doc))]
|
||||||
/// The registry of all Dioxus server functions.
|
/// The registry of all Dioxus server functions.
|
||||||
pub struct DioxusServerFnRegistry;
|
pub struct DioxusServerFnRegistry;
|
||||||
|
|
||||||
#[cfg(any(feature = "ssr"))]
|
#[cfg(feature = "ssr")]
|
||||||
impl server_fn::ServerFunctionRegistry<DioxusServerContext> for DioxusServerFnRegistry {
|
impl server_fn::ServerFunctionRegistry<DioxusServerContext> for DioxusServerFnRegistry {
|
||||||
type Error = ServerRegistrationFnError;
|
type Error = ServerRegistrationFnError;
|
||||||
|
|
||||||
fn register(
|
fn register_explicit(
|
||||||
|
prefix: &'static str,
|
||||||
url: &'static str,
|
url: &'static str,
|
||||||
server_function: std::sync::Arc<ServerFnTraitObj>,
|
server_function: ServerFunction,
|
||||||
encoding: server_fn::Encoding,
|
encoding: server_fn::Encoding,
|
||||||
) -> Result<(), Self::Error> {
|
) -> Result<(), Self::Error> {
|
||||||
// store it in the hashmap
|
// store it in the hashmap
|
||||||
@@ -33,10 +79,7 @@ impl server_fn::ServerFunctionRegistry<DioxusServerContext> for DioxusServerFnRe
|
|||||||
.map_err(|e| ServerRegistrationFnError::Poisoned(e.to_string()))?;
|
.map_err(|e| ServerRegistrationFnError::Poisoned(e.to_string()))?;
|
||||||
let prev = write.insert(
|
let prev = write.insert(
|
||||||
url,
|
url,
|
||||||
ServerFunction {
|
ServerFnTraitObj::new(prefix, url, encoding, server_function),
|
||||||
trait_obj: server_function,
|
|
||||||
encoding,
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
|
|
||||||
// if there was already a server function with this key,
|
// if there was already a server function with this key,
|
||||||
@@ -53,27 +96,32 @@ impl server_fn::ServerFunctionRegistry<DioxusServerContext> for DioxusServerFnRe
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the server function registered at the given URL, or `None` if no function is registered at that URL.
|
fn register(
|
||||||
fn get(url: &str) -> Option<ServerFunction> {
|
url: &'static str,
|
||||||
REGISTERED_SERVER_FUNCTIONS
|
server_function: ServerFunction,
|
||||||
.read()
|
encoding: server_fn::Encoding,
|
||||||
.ok()
|
) -> Result<(), Self::Error> {
|
||||||
.and_then(|fns| fns.get(url).cloned())
|
Self::register_explicit("", url, server_function, encoding)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the server function registered at the given URL, or `None` if no function is registered at that URL.
|
/// Returns the server function registered at the given URL, or `None` if no function is registered at that URL.
|
||||||
fn get_trait_obj(url: &str) -> Option<std::sync::Arc<ServerFnTraitObj>> {
|
fn get(url: &str) -> Option<server_fn::ServerFnTraitObj<DioxusServerContext>> {
|
||||||
REGISTERED_SERVER_FUNCTIONS
|
REGISTERED_SERVER_FUNCTIONS
|
||||||
.read()
|
.read()
|
||||||
.ok()
|
.ok()
|
||||||
.and_then(|fns| fns.get(url).map(|f| f.trait_obj.clone()))
|
.and_then(|fns| fns.get(url).map(|inner| inner.0.clone()))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the server function registered at the given URL, or `None` if no function is registered at that URL.
|
||||||
|
fn get_trait_obj(url: &str) -> Option<server_fn::ServerFnTraitObj<DioxusServerContext>> {
|
||||||
|
Self::get(url)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_encoding(url: &str) -> Option<server_fn::Encoding> {
|
fn get_encoding(url: &str) -> Option<server_fn::Encoding> {
|
||||||
REGISTERED_SERVER_FUNCTIONS
|
REGISTERED_SERVER_FUNCTIONS
|
||||||
.read()
|
.read()
|
||||||
.ok()
|
.ok()
|
||||||
.and_then(|fns| fns.get(url).map(|f| f.encoding.clone()))
|
.and_then(|fns| fns.get(url).map(|f| f.encoding()))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a list of all registered server functions.
|
/// Returns a list of all registered server functions.
|
||||||
@@ -103,16 +151,16 @@ pub enum ServerRegistrationFnError {
|
|||||||
///
|
///
|
||||||
/// Server functions are created using the `server` macro.
|
/// Server functions are created using the `server` macro.
|
||||||
///
|
///
|
||||||
/// The function should be registered by calling `ServerFn::register()`. The set of server functions
|
/// The set of server functions
|
||||||
/// can be queried on the server for routing purposes by calling [server_fn::ServerFunctionRegistry::get].
|
/// can be queried on the server for routing purposes by calling [server_fn::ServerFunctionRegistry::get].
|
||||||
///
|
///
|
||||||
/// Technically, the trait is implemented on a type that describes the server function's arguments, not the function itself.
|
/// Technically, the trait is implemented on a type that describes the server function's arguments, not the function itself.
|
||||||
pub trait ServerFn: server_fn::ServerFn<DioxusServerContext> {
|
pub trait DioxusServerFn: server_fn::ServerFn<DioxusServerContext> {
|
||||||
/// Registers the server function, allowing the client to query it by URL.
|
/// Registers the server function, allowing the client to query it by URL.
|
||||||
#[cfg(any(feature = "ssr", doc))]
|
#[cfg(any(feature = "ssr", doc))]
|
||||||
fn register() -> Result<(), server_fn::ServerFnError> {
|
fn register_explicit() -> Result<(), server_fn::ServerFnError> {
|
||||||
Self::register_in::<DioxusServerFnRegistry>()
|
Self::register_in_explicit::<DioxusServerFnRegistry>()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> ServerFn for T where T: server_fn::ServerFn<DioxusServerContext> {}
|
impl<T> DioxusServerFn for T where T: server_fn::ServerFn<DioxusServerContext> {}
|
||||||
Reference in new issue
Block a user