mirror of
https://github.com/leptos-rs/leptos
synced 2024-11-10 06:44:17 +00:00
fix issue with redirects in server fns creating multiple Location headers (#550)
This commit is contained in:
parent
a2eaf9b3ee
commit
322041917d
4 changed files with 40 additions and 26 deletions
|
@ -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(
|
||||
|
|
|
@ -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.)
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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<dyn Fn(&web_sys::FormData)>;
|
||||
type OnResponse = Rc<dyn Fn(&web_sys::Response)>;
|
||||
|
@ -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!("<Form/> error while POSTing: {e:#?}");
|
||||
error!("<Form/> 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);
|
||||
|
|
Loading…
Reference in a new issue