Skip to content

Commit

Permalink
Make server fn responses work on both success and failure
Browse files Browse the repository at this point in the history
  • Loading branch information
SleeplessOne1917 committed Jan 13, 2024
1 parent 1472aaa commit 7d1583a
Show file tree
Hide file tree
Showing 7 changed files with 48 additions and 33 deletions.
6 changes: 3 additions & 3 deletions examples/action-form-error-handling/src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,9 @@ fn HomePage() -> impl IntoView {
let do_something_action = Action::<DoSomething, _>::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! {
<h1>"Test the action form!"</h1>
Expand Down
1 change: 1 addition & 0 deletions integrations/actix/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"]
Expand Down
15 changes: 6 additions & 9 deletions integrations/actix/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
*,
};
Expand Down Expand Up @@ -351,7 +351,7 @@ pub fn handle_server_fns_with_context(
HttpResponse::SeeOther()
.insert_header((
header::LOCATION,
url.with_server_fn_error(
<url::Url as WithServerFn<'_, ()>>::with_server_fn_error(url,
&e,
fn_name.as_str(),
)
Expand Down Expand Up @@ -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")]
Expand Down
2 changes: 1 addition & 1 deletion integrations/utils/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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, ""),
)
Expand Down
5 changes: 4 additions & 1 deletion leptos/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
32 changes: 15 additions & 17 deletions router/src/components/form.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -464,16 +459,19 @@ where
let action_url = effect_action_url.clone();

Effect::new_isomorphic(move |_| {
let results = use_context::<HashSet<ServerFnUrlResponse<O>>>();
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::<ServerFnContext>();

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::<O>(
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()));
}
}
});

Expand Down
20 changes: 18 additions & 2 deletions server_fn/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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<T: Clone> {
Expand Down Expand Up @@ -657,7 +673,7 @@ fn get_server_url() -> &'static str {
}

#[doc(hidden)]
pub fn query_to_responses<T: Clone + DeserializeOwned + Hash + Eq>(query: &str) -> HashSet<ServerFnUrlResponse<T>> {
pub fn query_to_responses<T: Clone + DeserializeOwned + Serialize + 'static>(query: &str) -> Vec<ServerFnUrlResponse<T>> {
// 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.
Expand Down

0 comments on commit 7d1583a

Please sign in to comment.