From 18eecd960608fa328f56618ef416168f5e2bf66d Mon Sep 17 00:00:00 2001 From: Clemente Date: Fri, 20 Jan 2023 18:11:49 -0300 Subject: [PATCH] Use URLSearchParams to handle client side query param logic --- router/Cargo.toml | 2 +- router/src/history/url.rs | 51 +++++++++++++++++++++++++++++++++------ 2 files changed, 45 insertions(+), 8 deletions(-) diff --git a/router/Cargo.toml b/router/Cargo.toml index 953e9fde6..94b7a3cd8 100644 --- a/router/Cargo.toml +++ b/router/Cargo.toml @@ -56,7 +56,7 @@ features = [ [features] default = [] csr = ["leptos/csr"] -hydrate = ["leptos/hydrate", "dep:url"] +hydrate = ["leptos/hydrate"] ssr = ["leptos/ssr", "dep:url", "dep:regex"] stable = ["leptos/stable"] diff --git a/router/src/history/url.rs b/router/src/history/url.rs index cf5bc6565..b46f735c9 100644 --- a/router/src/history/url.rs +++ b/router/src/history/url.rs @@ -1,5 +1,10 @@ use crate::ParamsMap; -use std::borrow::Cow; +#[cfg(not(feature = "ssr"))] +use js_sys::{try_iter, Array, JsString}; +#[cfg(not(feature = "ssr"))] +use wasm_bindgen::JsCast; +#[cfg(not(feature = "ssr"))] +use wasm_bindgen::JsValue; #[derive(Debug, Default, Clone, PartialEq, Eq)] pub struct Url { @@ -25,11 +30,41 @@ pub fn escape(s: &str) -> String { js_sys::encode_uri(s).as_string().unwrap() } +#[cfg(not(feature = "ssr"))] impl TryFrom<&str> for Url { type Error = String; fn try_from(url: &str) -> Result { - let url = url::Url::parse(&normalize_wasm_url(url)).map_err(|e| e.to_string())?; + let fake_host = String::from("http://leptos"); + let url = web_sys::Url::new_with_base(url, &fake_host).map_js_error()?; + Ok(Self { + origin: url.origin(), + pathname: url.pathname(), + search: url.search(), + search_params: ParamsMap( + try_iter(&url.search_params()) + .map_js_error()? + .ok_or("Failed to use URLSearchParams as an iterator".to_string())? + .map(|value| { + let array: Array = value.map_js_error()?.dyn_into().map_js_error()?; + Ok(( + array.get(0).dyn_into::().map_js_error()?.into(), + array.get(1).dyn_into::().map_js_error()?.into(), + )) + }) + .collect::, Self::Error>>()?, + ), + hash: url.hash(), + }) + } +} + +#[cfg(feature = "ssr")] +impl TryFrom<&str> for Url { + type Error = String; + + fn try_from(url: &str) -> Result { + let url = url::Url::parse(url).map_err(|e| e.to_string())?; Ok(Self { origin: url.origin().unicode_serialization(), pathname: url.path().to_string(), @@ -44,12 +79,14 @@ impl TryFrom<&str> for Url { } } -#[cfg(feature = "ssr")] -fn normalize_wasm_url(url: &str) -> Cow<'_, str> { - Cow::Borrowed(url) +#[cfg(not(feature = "ssr"))] +trait MapJsError { + fn map_js_error(self) -> Result; } #[cfg(not(feature = "ssr"))] -fn normalize_wasm_url(url: &str) -> Cow<'_, str> { - Cow::Owned(format!("http://leptos{}", url)) +impl MapJsError for Result { + fn map_js_error(self) -> Result { + self.map_err(|e| e.as_string().unwrap_or_default()) + } }