Skip to content

Commit

Permalink
fix: properly handle trailing / in splat routes (closes #1764) (#1890)
Browse files Browse the repository at this point in the history
  • Loading branch information
gbj authored Oct 14, 2023
1 parent 07f2cbf commit 8eed999
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 3 deletions.
1 change: 1 addition & 0 deletions router/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
4 changes: 2 additions & 2 deletions router/src/history/url.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
Expand Down
14 changes: 13 additions & 1 deletion router/src/matching/matcher.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand All @@ -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);
}
}
Expand Down
46 changes: 46 additions & 0 deletions router/tests/matcher.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand All @@ -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" => "///"
)
})
);
}
}
}

0 comments on commit 8eed999

Please sign in to comment.