feat(rustproxy): introduce a Rust-powered proxy engine and workspace with core crates for proxy functionality, ACME/TLS support, passthrough and HTTP proxies, metrics, nftables integration, routing/security, management IPC, tests, and README updates
This commit is contained in:
65
rust/crates/rustproxy-routing/src/matchers/path.rs
Normal file
65
rust/crates/rustproxy-routing/src/matchers/path.rs
Normal file
@@ -0,0 +1,65 @@
|
||||
/// Match a URL path against a pattern supporting wildcards.
|
||||
///
|
||||
/// Supported patterns:
|
||||
/// - `/api/*` matches `/api/anything` (single level)
|
||||
/// - `/api/**` matches `/api/any/depth/here`
|
||||
/// - `/exact/path` exact match
|
||||
/// - `/prefix*` prefix match
|
||||
pub fn path_matches(pattern: &str, path: &str) -> bool {
|
||||
// Exact match
|
||||
if pattern == path {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Double-star: match any depth
|
||||
if pattern.ends_with("/**") {
|
||||
let prefix = &pattern[..pattern.len() - 3];
|
||||
return path == prefix || path.starts_with(&format!("{}/", prefix));
|
||||
}
|
||||
|
||||
// Single-star at end: match single path segment
|
||||
if pattern.ends_with("/*") {
|
||||
let prefix = &pattern[..pattern.len() - 2];
|
||||
if path == prefix {
|
||||
return true;
|
||||
}
|
||||
if path.starts_with(&format!("{}/", prefix)) {
|
||||
let rest = &path[prefix.len() + 1..];
|
||||
// Single level means no more slashes
|
||||
return !rest.contains('/');
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Star anywhere: use glob matching
|
||||
if pattern.contains('*') {
|
||||
return glob_match::glob_match(pattern, path);
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_exact_path() {
|
||||
assert!(path_matches("/api/users", "/api/users"));
|
||||
assert!(!path_matches("/api/users", "/api/posts"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_single_wildcard() {
|
||||
assert!(path_matches("/api/*", "/api/users"));
|
||||
assert!(path_matches("/api/*", "/api/posts"));
|
||||
assert!(!path_matches("/api/*", "/api/users/123"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_double_wildcard() {
|
||||
assert!(path_matches("/api/**", "/api/users"));
|
||||
assert!(path_matches("/api/**", "/api/users/123"));
|
||||
assert!(path_matches("/api/**", "/api/users/123/posts"));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user