Skip to content

feat: add wildcard path route - #586

Merged
ElijahAhianyo merged 37 commits into
cot-rs:masterfrom
dharshan-0:wildcard-feature
Aug 20, 2026
Merged

feat: add wildcard path route#586
ElijahAhianyo merged 37 commits into
cot-rs:masterfrom
dharshan-0:wildcard-feature

Conversation

@dharshan-0

@dharshan-0 dharshan-0 commented Jun 3, 2026

Copy link
Copy Markdown
Contributor

Related issue or discussion

Description

It closes #545 by adding wildcard routing feature.

It uses this {*param_name} to define wildcard.

Route::with_handler_and_name("/random/{*path}", generate_random, "generate-random"),

Type of change

  • Bug fix
  • New feature
  • Documentation
  • Refactor / cleanup
  • Performance improvement
  • Other (describe above)

Checklist

  • I've read the contributing guide
  • Tests pass locally (just test-all)
  • Code passes clippy (just clippy)
  • Code is properly formatted (cargo fmt)
  • New tests added (regression test for bugs, coverage for new features)
  • Documentation (both code and site) updated (if applicable)

@github-actions github-actions Bot added A-docs Area: Documentation C-lib Crate: cot (main library crate) labels Jun 3, 2026
@codecov

codecov Bot commented Jun 3, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 99.04762% with 2 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
cot/src/router/path.rs 98.07% 1 Missing and 1 partial ⚠️
Flag Coverage Δ
rust 90.29% <99.04%> (+0.07%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
cot/src/router.rs 93.53% <100.00%> (+1.32%) ⬆️
cot/src/router/path.rs 99.23% <98.07%> (-0.43%) ⬇️
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@ElijahAhianyo ElijahAhianyo left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dharshan-0 Thanks a lot for your contribution. This is a great start! Let's address the comments, and it's good to merge.

Comment thread cot/src/router/path.rs Outdated
Comment thread cot/src/router/path.rs Outdated
Comment thread cot/src/router/path.rs Outdated
Comment thread cot/src/router/path.rs Outdated
@dharshan-0

dharshan-0 commented Jun 8, 2026

Copy link
Copy Markdown
Contributor Author

@ElijahAhianyo Thanks for your comments, I will look into it.

@dharshan-0
dharshan-0 marked this pull request as draft June 8, 2026 16:30
@dharshan-0
dharshan-0 marked this pull request as ready for review June 10, 2026 07:52
@dharshan-0
dharshan-0 requested a review from ElijahAhianyo June 10, 2026 07:53
Comment thread cot/src/router/path.rs
Comment thread cot/src/router/path.rs Outdated

@ElijahAhianyo ElijahAhianyo left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dharshan-0 Thanks for your contribution once again!

@dharshan-0
dharshan-0 marked this pull request as ready for review June 28, 2026 13:49
@dharshan-0
dharshan-0 requested a review from seqre June 29, 2026 00:44
@dharshan-0
dharshan-0 requested a review from ElijahAhianyo July 6, 2026 14:44
@seqre seqre changed the title Added wildcard feature feat: add wildcard path route Jul 6, 2026
Comment thread cot/src/router.rs Outdated
Comment thread cot/src/router/path.rs Outdated
Comment on lines +224 to +265
pub(crate) fn compare_weights(a: &[u8], b: &[u8]) -> std::cmp::Ordering {
let max_len = std::cmp::max(a.len(), b.len());
let mut score: isize = 0;
let mut lexical_order_a = String::with_capacity(a.len());
let mut lexical_order_b = String::with_capacity(b.len());

for i in 0..max_len {
let (wa, wb) = match (a.get(i), b.get(i)) {
(None, _) => return std::cmp::Ordering::Less,
(_, None) => return std::cmp::Ordering::Greater,
(Some(&w), Some(&v)) => (w, v),
};
lexical_order_a.push(char::from_digit(u32::from(wa), 10).unwrap());
lexical_order_b.push(char::from_digit(u32::from(wb), 10).unwrap());

if wa == 2 && wb == 2 {
return lexical_order_a.cmp(&lexical_order_b);
}
if wa == 2 {
return std::cmp::Ordering::Greater;
}
if wb == 2 {
return std::cmp::Ordering::Less;
}
if wa != wb {
if wa < wb {
score += 1;
} else {
score -= 1;
}
}
}

if score != 0 {
return if score > 0 {
std::cmp::Ordering::Less
} else {
std::cmp::Ordering::Greater
};
}

lexical_order_a.cmp(&lexical_order_b)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why this whole logic is here? Why can't you just compare the weights vectors?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A direct comparison of the weight vectors is purely lexicographic it only considers the first segment where the routes differ and ignores everything after that.

For example:

/1 / 2 / {*rest}
/1 /{id}/ 3 / 4 / 5

The first difference is 2 (static) vs {id} (parameter), so a lexicographic comparison immediately ranks the first route ahead of the second. However, the second route is actually more specific overall.

Let me know, if Iam wrong @seqre .

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @dharshan-0, sorry for the slow turnaround on this.

Taking another look, I think we've hit the limits of storing routes in a Vec. It makes structural validation and conflict detection (like params vs. wildcards) too brittle to handle well, and that's really a limitation of the underlying data structure rather than your approach to it. I'm working on moving the router to a radix trie, which should let us catch these conflicts properly at a structural level instead of relying on priority ordering.

Given that, I think your wildcard implementation is solid up to the point before you started handling the case where params take precedence over wildcards. That part's good enough to merge as-is. I don't think we need to solve that precedence case in this PR (or possibly at all, once the trie is in place).

Could you revert the commits where you handled that precedence logic? Happy to review and merge right after.

Thanks for your patience on this one, and sorry again for sitting on it so long.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, thats ok for me. I will remove the presendence logic and commit it, Thankyou for your response.

@dharshan-0
dharshan-0 requested a review from seqre July 7, 2026 08:33
@dharshan-0
dharshan-0 marked this pull request as draft August 19, 2026 14:50
@dharshan-0
dharshan-0 marked this pull request as ready for review August 19, 2026 17:35

@ElijahAhianyo ElijahAhianyo left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Again @dharshan-0 Thanks for your contribution and patience!

@ElijahAhianyo
ElijahAhianyo enabled auto-merge (squash) August 20, 2026 16:27
@ElijahAhianyo
ElijahAhianyo merged commit 42bdf61 into cot-rs:master Aug 20, 2026
22 checks passed
@cotbot cotbot Bot mentioned this pull request Aug 20, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-docs Area: Documentation C-lib Crate: cot (main library crate)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support Wildcard in Routes

3 participants