diff --git a/integrations/axum/src/lib.rs b/integrations/axum/src/lib.rs index 9e674476c0..66821c3ebd 100644 --- a/integrations/axum/src/lib.rs +++ b/integrations/axum/src/lib.rs @@ -251,11 +251,6 @@ async fn handle_server_fns_inner( res_options_inner.headers.clone(), ); - if let Some(header_ref) = res.headers_mut() - { - header_ref.extend(res_headers.drain()); - }; - if accept_header == Some("application/json") || accept_header == Some( @@ -285,6 +280,12 @@ async fn handle_server_fns_inner( Some(status) => res.status(status), None => res, }; + // This must be after the default referrer + // redirect so that it overwrites the one above + if let Some(header_ref) = res.headers_mut() + { + header_ref.extend(res_headers.drain()); + }; match serialized { Payload::Binary(data) => res .header( diff --git a/leptos_server/src/action.rs b/leptos_server/src/action.rs index 6242046c3e..c88c592ca8 100644 --- a/leptos_server/src/action.rs +++ b/leptos_server/src/action.rs @@ -100,7 +100,7 @@ where /// Updates whether the action is currently pending. pub fn set_pending(&self, pending: bool) { - self.0.with_value(|a| a.pending.set(pending)) + self.0.try_with_value(|a| a.pending.set(pending)); } /// The URL associated with the action (typically as part of a server function.) diff --git a/router/Cargo.toml b/router/Cargo.toml index f7d2e6c03d..06760f0dab 100644 --- a/router/Cargo.toml +++ b/router/Cargo.toml @@ -12,7 +12,7 @@ description = "Router for the Leptos web framework." leptos = { workspace = true } cfg-if = "1" common_macros = "0.1" -gloo-net = "0.2" +gloo-net = { version = "0.2", features = ["http"] } lazy_static = "1" linear-map = "1" log = "0.4" diff --git a/router/src/components/form.rs b/router/src/components/form.rs index de392ab010..04a0e84939 100644 --- a/router/src/components/form.rs +++ b/router/src/components/form.rs @@ -1,8 +1,9 @@ -use crate::{use_navigate, use_resolved_path, ToHref}; +use crate::{use_navigate, use_resolved_path, ToHref, Url}; use leptos::*; use std::{error::Error, rc::Rc}; use wasm_bindgen::{JsCast, UnwrapThrowExt}; use wasm_bindgen_futures::JsFuture; +use web_sys::RequestRedirect; type OnFormData = Rc; type OnResponse = Rc; @@ -90,12 +91,13 @@ where let res = gloo_net::http::Request::post(&action) .header("Accept", "application/json") .header("Content-Type", &enctype) + .redirect(RequestRedirect::Follow) .body(params) .send() .await; match res { Err(e) => { - log::error!("
error while POSTing: {e:#?}"); + error!(" error while POSTing: {e:#?}"); if let Some(error) = error { error.set(Some(Box::new(e))); } @@ -110,15 +112,22 @@ where if let Some(on_response) = on_response.clone() { on_response(resp.as_raw()); } - - if resp.status() == 303 { - if let Some(redirect_url) = - resp.headers().get("Location") - { - _ = navigate( - &redirect_url, - Default::default(), - ); + // Check all the logical 3xx responses that might + // get returned from a server function + if resp.redirected() { + let resp_url = &resp.url(); + match Url::try_from(resp_url.as_str()) { + Ok(url) => { + request_animation_frame(move || { + if let Err(e) = navigate( + &url.pathname, + Default::default(), + ) { + warn!("{}", e); + } + }); + } + Err(e) => warn!("{}", e), } } } @@ -207,7 +216,7 @@ where input.set(Some(data)); action.set_pending(true); } - Err(e) => log::error!("{e}"), + Err(e) => error!("{e}"), } }); @@ -225,15 +234,19 @@ where .as_string() .expect("couldn't get String from JsString"), ) { - Ok(res) => value.set(Some(Ok(res))), - Err(e) => value.set(Some(Err( - ServerFnError::Deserialization(e.to_string()), - ))), + Ok(res) => { + value.try_set(Some(Ok(res))); + } + Err(e) => { + value.try_set(Some(Err( + ServerFnError::Deserialization(e.to_string()), + ))); + } } } - Err(e) => log::error!("{e:?}"), + Err(e) => error!("{e:?}"), }; - input.set(None); + input.try_set(None); action.set_pending(false); }); }); @@ -293,7 +306,7 @@ where let form_data = web_sys::FormData::new_with_form(&form).unwrap_throw(); let data = action_input_from_form_data(&form_data); match data { - Err(e) => log::error!("{e}"), + Err(e) => error!("{e}"), Ok(input) => { ev.prevent_default(); multi_action.dispatch(input);