Skip to content

Commit

Permalink
fix: properly handle trailing / in splat routes (closes #1764)
Browse files Browse the repository at this point in the history
  • Loading branch information
gbj committed Oct 12, 2023
1 parent 468e167 commit 5a33870
Showing 1 changed file with 18 additions and 19 deletions.
37 changes: 18 additions & 19 deletions router/src/matching/matcher.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ impl Matcher {
};
let segments = pattern
.split('/')
.filter(|n| !n.is_empty())
.map(|n| n.to_string())
.collect::<Vec<_>>();

Expand All @@ -56,13 +57,14 @@ impl Matcher {
let loc_len = loc_segments.len();
let len_diff: i32 = loc_len as i32 - self.len as i32;

leptos::logging::log!("{:?}\n{loc_segments:?}", self.segments);

// quick path: not a match if
// 1) matcher has add'l segments not found in location
// 2) location has add'l segments, there's no splat, and partial matches not allowed
// 2) location has add'l segments, there's no splat, and partial matches not allowed, or
// 3) there is a splat, and additional trailing slashes
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 @@ -72,34 +74,31 @@ impl Matcher {
let mut params = ParamsMap::new();

let segments = self.segments.iter();
let mut loc_segments_iter = loc_segments.iter();
for segment in segments {
for (segment, loc_segment) in segments.zip(loc_segments) {
// if it's a splat, move on
if segment.starts_with('*') {
_ = loc_segments_iter.next();
break;
}

if let Some(loc_segment) = loc_segments_iter.next() {
if let Some(param_name) = segment.strip_prefix(':') {
params.insert(param_name.into(), (*loc_segment).into());
} else if segment != loc_segment {
// if any segment doesn't match and isn't a param, there's no path match
return None;
}
if let Some(param_name) = segment.strip_prefix(':') {
params.insert(param_name.into(), (*loc_segment).into());
} else if segment != loc_segment {
// if any segment doesn't match and isn't a param, there's no path match
return None;
}

if !segment.is_empty() {
path.push('/');
}
path.push_str(loc_segment);
if !segment.is_empty() {
path.push('/');
}
path.push_str(loc_segment);
}

if let Some(splat) = &self.splat {
if !splat.is_empty() {
let mut value = String::new();
_ = loc_segments_iter.next(); // eat the next `/`
for loc_segment in loc_segments_iter {
for loc_segment in
location.split('/').skip(self.segments.len() + 2)
{
value.push('/');
value.push_str(loc_segment);
}
Expand Down

0 comments on commit 5a33870

Please sign in to comment.