fix: properly handle trailing / in splat routes (closes #1764) (#1890)

This commit is contained in:
Greg Johnston 2023-10-14 08:37:31 -04:00 committed by GitHub
parent 07f2cbfbba
commit 8eed999611
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 62 additions and 3 deletions

View file

@ -31,6 +31,7 @@ wasm-bindgen = { version = "0.2" }
wasm-bindgen-futures = { version = "0.4" }
lru = { version = "0.11", optional = true }
serde_json = "1.0.96"
itertools = "0.11.0"
[dependencies.web-sys]
version = "0.3"

View file

@ -36,8 +36,8 @@ impl TryFrom<&str> for Url {
type Error = String;
fn try_from(url: &str) -> Result<Self, Self::Error> {
let fake_host = "http://leptos";
let url = web_sys::Url::new_with_base(url, fake_host).map_js_error()?;
let url =
web_sys::Url::new(&format!("http://leptos{url}")).map_js_error()?;
Ok(Self {
origin: url.origin(),
pathname: url.pathname(),

View file

@ -62,6 +62,8 @@ impl Matcher {
// 2) location has add'l segments, there's no splat, and partial matches not allowed
if loc_len < self.len
|| (len_diff > 0 && self.splat.is_none() && !self.partial)
|| (self.splat.is_none()
&& location.split('/').count() > (2 * (loc_segments.len() + 1)))
{
None
}
@ -86,11 +88,21 @@ impl Matcher {
if let Some(splat) = &self.splat {
if !splat.is_empty() {
let value = if len_diff > 0 {
let mut value = if len_diff > 0 {
loc_segments[self.len..].join("/")
} else {
"".into()
};
// add trailing slashes to splat
let trailing_slashes = location
.chars()
.rev()
.take_while(|n| *n == '/')
.skip(1)
.collect::<String>();
value.push_str(&trailing_slashes);
params.insert(splat.into(), value);
}
}

View file

@ -78,6 +78,22 @@ cfg_if! {
);
}
#[test]
fn create_matcher_should_include_remaining_unmatched_location_as_param_when_ending_in_asterisk_and_name_2(
) {
let matcher = Matcher::new("/foo/*something");
let matched = matcher.test("/foo/baz/qux");
assert_eq!(
matched,
Some(PathMatch {
path: "/foo".into(),
params: params_map!(
"something" => "baz/qux"
)
})
);
}
#[test]
fn create_matcher_should_include_empty_param_when_perfect_match_ends_in_asterisk_and_name() {
let matcher = Matcher::new("/foo/bar/*something");
@ -92,5 +108,35 @@ cfg_if! {
})
);
}
#[test]
fn matcher_should_include_multiple_slashes_in_a_splat_route() {
let matcher = Matcher::new("/*any");
let matched = matcher.test("////");
assert_eq!(
matched,
Some(PathMatch {
path: "".into(),
params: params_map!(
"any" => "///"
)
})
);
}
#[test]
fn matcher_should_include_multiple_slashes_in_a_splat_route_after_others() {
let matcher = Matcher::new("/foo/bar/*any");
let matched = matcher.test("/foo/bar////");
assert_eq!(
matched,
Some(PathMatch {
path: "/foo/bar".into(),
params: params_map!(
"any" => "///"
)
})
);
}
}
}