Add support for multiple path matching
All checks were successful
/ build (push) Successful in 4m11s

This commit is contained in:
Dustin Thomas 2025-09-09 19:27:51 -05:00
parent 02ff3ad96f
commit 3fdd22c079
Signed by: cptlobster
GPG key ID: 33D607425C830B4C
4 changed files with 57 additions and 20 deletions

View file

@ -4,11 +4,7 @@ from = "a"
to = "https://cptlobster.dev"
[[routes]]
from = "b"
to = "https://www.youtube.com/watch?v=dQw4w9WgXcQ"
[[routes]]
from = "d"
from = ["b", "d"]
to = "https://www.youtube.com/watch?v=dQw4w9WgXcQ"
# This is a simple regex matcher. It will match any string that ends in "ic".

View file

@ -57,35 +57,68 @@ pub struct Config {
#[derive(Debug, PartialEq, Serialize, Deserialize, Clone)]
#[serde(crate = "rocket::serde")]
pub struct Route {
from: String,
from: Multiable<String>,
to: String,
#[serde(default)]
using: MatcherType
}
#[derive(Debug, PartialEq, Serialize, Deserialize, Clone)]
#[serde(crate = "rocket::serde", untagged)]
enum Multiable<T> {
Single(T),
Multi(Vec<T>)
}
impl Route {
pub fn matches(&self, input: &str) -> bool {
match self.using {
MatcherType::Regex => {
let re = Regex::new(format!("^{}$", self.from).as_str()).unwrap();
match &self.from {
Multiable::Single(from) => match self.using {
MatcherType::Regex => {
let re = Regex::new(format ! ("^{}$", from).as_str()).unwrap();
re.is_match(input)
},
_ => self.from == input.to_string()
},
_ => *from == input.to_string()
}
Multiable::Multi(from_vec) => match self.using {
MatcherType::Regex => {
from_vec.into_iter().find(|from| {
let re = Regex::new(format ! ("^{}$", from).as_str()).unwrap();
re.is_match(input)
}).is_some()
},
_ => from_vec.into_iter().find(|from| **from == input.to_string()).is_some()
}
}
}
pub fn src(&self) -> String {
self.from.clone()
pub fn src(&self) -> Vec<String> {
match &self.from {
Multiable::Single(from) => vec![from.clone()],
Multiable::Multi(from_vec) => from_vec.clone()
}
}
pub fn dest(&self, input: &str) -> String {
match self.using {
MatcherType::Regex => {
let re = Regex::new(format!("^{}$", self.from).as_str()).unwrap();
match &self.from {
Multiable::Single(from) => match self.using {
MatcherType::Regex => {
let re = Regex::new(format ! ("^{}$", from).as_str()).unwrap();
let result = re.replace_all(input, self.to.clone());
result.clone().parse().unwrap()
},
_ => self.to.clone()
},
_ => self.to.clone()
Multiable::Multi(from_vec) => match self.using {
MatcherType::Regex => {
from_vec.into_iter().find(|from| {
let re = Regex::new(format!("^{}$", from).as_str()).unwrap();
let result = re.replace_all(input, self.to.clone());
result.clone().parse().unwrap()
}).unwrap().clone()
},
_ => self.to.clone()
}
}
}
}

View file

@ -29,7 +29,7 @@ use rocket_dyn_templates::{Template, tera::Tera, context};
async fn list_paths(cm: &State<ConfigManager>) -> Result<String, NoContent> {
let config = cm.get().await;
if config.hide_routes { return Err(NoContent) }
let all_routes = config.routes.iter().map(|r: &Route| r.src()).collect::<Vec<String>>();
let all_routes = config.routes.iter().flat_map(|r: &Route| r.src()).collect::<Vec<String>>();
if all_routes.is_empty() { Err(NoContent) } else {
Ok(all_routes.into_iter().map(|a| format!("/{}", a)).collect::<Vec<String>>().join("\n"))
}

View file

@ -12,9 +12,17 @@
{%- for route in config.routes %}
<li>
{%- if route.using == "regex" %}
<code>/{{ route.from }}</code>
{% if route.from is iterable %}
{% for r in route.from %}<code>/{{ r }}</code>{% if not loop.last %}, {% endif %}{% endfor %}
{% else %}
<code>/{{ route.from }}</code>
{% endif %}
{%- else %}
<a href="/{{ route.from }}">/{{ route.from }}</a>
{% if route.from is iterable %}
{% for r in route.from %}<a href="/{{ r }}">/{{ r }}</a>{% if not loop.last %}, {% endif %}{% endfor %}
{% else %}
<a href="/{{ route.from }}">/{{ route.from }}</a>
{% endif %}
{%- endif %}
({{ route.using }})
</li>