From 7d1583a0a0f4d6553102cae79a3a5b00cab7fa0a Mon Sep 17 00:00:00 2001 From: SleeplessOne1917 Date: Fri, 12 Jan 2024 23:25:20 -0500 Subject: [PATCH] Make server fn responses work on both success and failure --- .../action-form-error-handling/src/app.rs | 6 ++-- integrations/actix/Cargo.toml | 1 + integrations/actix/src/lib.rs | 15 ++++----- integrations/utils/src/lib.rs | 2 +- leptos/src/lib.rs | 5 ++- router/src/components/form.rs | 32 +++++++++---------- server_fn/src/lib.rs | 20 ++++++++++-- 7 files changed, 48 insertions(+), 33 deletions(-) diff --git a/examples/action-form-error-handling/src/app.rs b/examples/action-form-error-handling/src/app.rs index ab935e4485..27ea5fe29d 100644 --- a/examples/action-form-error-handling/src/app.rs +++ b/examples/action-form-error-handling/src/app.rs @@ -44,9 +44,9 @@ fn HomePage() -> impl IntoView { let do_something_action = Action::::server(); let value = Signal::derive(move || do_something_action.value().get().unwrap_or_else(|| Ok(String::new()))); - Effect::new_isomorphic(move |_| { - logging::log!("Got value = {:?}", value.get()); - }); + // Effect::new_isomorphic(move |_| { + // logging::log!("Got value = {:?}", value.get()); + // }); view! {

"Test the action form!"

diff --git a/integrations/actix/Cargo.toml b/integrations/actix/Cargo.toml index 8c21885a11..1809b66f42 100644 --- a/integrations/actix/Cargo.toml +++ b/integrations/actix/Cargo.toml @@ -20,6 +20,7 @@ parking_lot = "0.12.1" regex = "1.7.0" tracing = "0.1.37" tokio = { version = "1", features = ["rt", "fs"] } +url = "2.5.0" [features] nonce = ["leptos/nonce"] diff --git a/integrations/actix/src/lib.rs b/integrations/actix/src/lib.rs index 54b9311c81..ad72407046 100644 --- a/integrations/actix/src/lib.rs +++ b/integrations/actix/src/lib.rs @@ -20,7 +20,7 @@ use actix_web::{ use futures::{Stream, StreamExt}; use leptos::{ leptos_server::{server_fn_by_path, Payload}, - server_fn::Encoding, + server_fn::{Encoding, ServerFnContext}, ssr::render_to_stream_with_prefix_undisposed_with_context_and_block_replacement, *, }; @@ -351,7 +351,7 @@ pub fn handle_server_fns_with_context( HttpResponse::SeeOther() .insert_header(( header::LOCATION, - url.with_server_fn_error( + >::with_server_fn_error(url, &e, fn_name.as_str(), ) @@ -804,13 +804,10 @@ fn provide_contexts(req: &HttpRequest, res_options: ResponseOptions) { provide_context(MetaContext::new()); provide_context(res_options); provide_context(req.clone()); - // TODO: Fix - // if let Some(query) = req.uri().query() { - // leptos::logging::log!("query = {query}"); - // provide_context(query_to_responses( - // query - // )); - // } + if let Some(query) = req.uri().query() { + leptos::logging::log!("query = {query}"); + provide_context(ServerFnContext::new(String::from(query))); + } provide_server_redirect(redirect); #[cfg(feature = "nonce")] diff --git a/integrations/utils/src/lib.rs b/integrations/utils/src/lib.rs index fca64f2fec..73f0c8ebdd 100644 --- a/integrations/utils/src/lib.rs +++ b/integrations/utils/src/lib.rs @@ -167,7 +167,7 @@ pub async fn build_async_response( pub fn referrer_to_url(referer: &str, fn_name: &str) -> Url { Url::parse( - &Regex::new(&format!(r"(?:\?|&)?server_fn_error_{fn_name}=[^&]+")) + &Regex::new(&format!(r"(?:\?|&)?server_fn_response_{fn_name}=[^&]+")) .unwrap() .replace(referer, ""), ) diff --git a/leptos/src/lib.rs b/leptos/src/lib.rs index 5c32d8a1fc..a300d8dbdd 100644 --- a/leptos/src/lib.rs +++ b/leptos/src/lib.rs @@ -187,7 +187,10 @@ pub use leptos_server::{ create_server_multi_action, Action, MultiAction, ServerFn, ServerFnError, ServerFnErrorErr, }; -pub use server_fn::{self, query_to_responses, ServerFn as _}; +pub use server_fn::{ + self, query_to_responses, ServerFn as _, ServerFnContext, + ServerFnUrlResponse, +}; mod error_boundary; pub use error_boundary::*; mod animated_show; diff --git a/router/src/components/form.rs b/router/src/components/form.rs index 1509bfe5e6..e47da6a25e 100644 --- a/router/src/components/form.rs +++ b/router/src/components/form.rs @@ -2,14 +2,9 @@ use crate::{ hooks::has_router, use_navigate, use_resolved_path, NavigateOptions, ToHref, Url, }; -use leptos::{ - html::form, - logging::*, - server_fn::ServerFnUrlResponse, - *, -}; +use leptos::{html::form, logging::*, *}; use serde::{de::DeserializeOwned, Serialize}; -use std::{collections::HashSet, error::Error, rc::Rc}; +use std::{error::Error, rc::Rc}; use wasm_bindgen::{JsCast, UnwrapThrowExt}; use wasm_bindgen_futures::JsFuture; use web_sys::RequestRedirect; @@ -464,16 +459,19 @@ where let action_url = effect_action_url.clone(); Effect::new_isomorphic(move |_| { - let results = use_context::>>(); - if let Some(result) = results - .map(|results| { - results - .into_iter() - .find(|e| effect_action_url.contains(e.name())) - }) - .flatten() - { - value.try_set(Some(result.get())); + let context = use_context::(); + + if let Some(context) = context { + leptos::logging::log!("Got context in iso effect with query = {}", context.get_query()); + if let Some(result) = query_to_responses::( + context.get_query() + ) + .into_iter() + .find(|r| effect_action_url.contains(r.name())) + { + leptos::logging::log!("iso effefct got match!"); + value.try_set(Some(result.get())); + } } }); diff --git a/server_fn/src/lib.rs b/server_fn/src/lib.rs index b53d718561..e478078e73 100644 --- a/server_fn/src/lib.rs +++ b/server_fn/src/lib.rs @@ -96,7 +96,7 @@ pub use serde; use serde::{de::DeserializeOwned, Serialize, Deserialize}; pub use server_fn_macro_default::server; use url::Url; -use std::{future::Future, pin::Pin, str::FromStr, collections::HashSet, hash::Hash, cmp::Eq}; +use std::{future::Future, pin::Pin, str::FromStr, hash::Hash, cmp::Eq}; #[cfg(any(feature = "ssr", doc))] use syn::parse_quote; // used by the macro @@ -599,6 +599,22 @@ where } } +#[doc(hidden)] +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct ServerFnContext(String); + +impl ServerFnContext { + pub fn new(query: String) -> Self { + Self(query) + } + + pub fn get_query(&self) -> &str { + &self.0 + } +} + + + /// TODO: Write Documentation #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Hash)] pub struct ServerFnUrlResponse { @@ -657,7 +673,7 @@ fn get_server_url() -> &'static str { } #[doc(hidden)] -pub fn query_to_responses(query: &str) -> HashSet> { +pub fn query_to_responses(query: &str) -> Vec> { // Url::parse needs an full absolute URL to parse correctly. // Since this function is only interested in the query pairs, // the specific scheme and domain do not matter.