From c32d11a949721c9e11836d6c8af0dfc82ed449fb Mon Sep 17 00:00:00 2001 From: theMackabu Date: Mon, 2 Sep 2024 20:04:50 -0700 Subject: [PATCH] add arg system back --- src/helpers.rs | 42 ------------------------- src/main.rs | 21 +++++++------ src/routes.rs | 77 +++++++++++++++++++++++++++++---------------- src/routes/match.rs | 0 4 files changed, 61 insertions(+), 79 deletions(-) create mode 100644 src/routes/match.rs diff --git a/src/helpers.rs b/src/helpers.rs index 5056af1..22dca7b 100644 --- a/src/helpers.rs +++ b/src/helpers.rs @@ -3,53 +3,11 @@ pub mod file; use actix_web::http::StatusCode; use mongodb::{bson::doc, sync::Database}; use rhai::{plugin::EvalAltResult, Engine, ParseError, AST}; -use std::collections::HashMap; pub mod prelude { pub use super::file::*; } -pub fn replace_chars(input: &str) -> String { - let replacements = HashMap::from([ - ('#', "_fhas"), - (':', "_fcol"), - ('-', "_fdas"), - ('@', "_fats"), - ('!', "_fexl"), - ('&', "_famp"), - ('^', "_fcar"), - ('~', "_ftil"), - ]); - - let mut result = String::with_capacity(input.len()); - - for c in input.chars() { - if let Some(replacement) = replacements.get(&c) { - result.push_str(replacement); - } else { - result.push(c); - } - } - - result -} - -// pub fn route_to_fn(input: &str) -> String { -// let input = super::replace_chars(input); -// let re = Regex::new(r#"\{([^{}\s]+)\}"#).unwrap(); -// let re_dot = Regex::new(r"\.(\w+)").unwrap(); -// -// let result = re.replace_all(&input, |captures: ®ex::Captures| { -// let content = captures.get(1).map_or("", |m| m.as_str()); -// format!("_arg_{content}") -// }); -// -// format!( -// "_route_fmt_{}", -// re_dot.replace_all(&result.replace("/", "_"), |captures: &Captures| format!("__d{}", rm_first(&captures[0]))) -// ) -// } - pub fn collection_exists(d: &Database, name: &String) -> Result> { let filter = doc! { "name": &name }; diff --git a/src/main.rs b/src/main.rs index 6770bea..b5f6b05 100644 --- a/src/main.rs +++ b/src/main.rs @@ -196,7 +196,7 @@ async fn handler(req: HttpRequest, config: Data) -> impl Responder { // move error handling here routes::parse::try_parse(&contents).await; - let route = match Route::get(&parse_slash(&url)).await { + let (route, args) = match Route::get(&parse_slash(&url)).await { Ok(route) => { let mut matched_url = url.to_owned(); @@ -219,11 +219,17 @@ async fn handler(req: HttpRequest, config: Data) -> impl Responder { } match Route::get(&matched_url).await { - Ok(route) => route, - Err(err) => error!(err), + Ok(matched) => (matched, vec![]), + Err(err) => match Route::search_for(&matched_url).await { + Some(matched) => matched, + None => error!(err), + }, } } - Err(err) => error!(err), + Err(err) => match Route::search_for(&url).await { + Some(matched) => matched, + None => error!(err), + }, }; let mut ast = match engine.compile(route.construct_fn()) { @@ -239,11 +245,6 @@ async fn handler(req: HttpRequest, config: Data) -> impl Responder { name => name, }; - let args = match route.args.to_owned() { - Some(args) => args, - None => vec![], - }; - match engine.call_fn::<(String, ContentType, StatusCode)>(&mut scope, &ast, fn_name, args) { Ok(response) => send!(response), Err(err) => { @@ -259,7 +260,7 @@ async fn handler(req: HttpRequest, config: Data) -> impl Responder { #[actix_web::main] async fn main() -> std::io::Result<()> { - set_env_sync!(RUST_LOG = "debug"); + set_env_sync!(RUST_LOG = "info"); globals::init(); let config = config::read(); diff --git a/src/routes.rs b/src/routes.rs index 512a71b..cc8fad4 100644 --- a/src/routes.rs +++ b/src/routes.rs @@ -35,7 +35,7 @@ pub enum RtKind { } pub struct RouteContainer { - inner: Route, + pub inner: Route, present_in_current_update: bool, } @@ -58,7 +58,27 @@ lazy_lock! { pub static ROUTES_INDEX: RtGlobalIndex = Arc::new(Mutex::new(DashMap::new())); } -fn match_route(route_template: &str, placeholders: &[&str], url: &str) -> Option> { +async fn get_fallback_route() -> Option<(Route, Vec)> { + let fallback_routes = [("not_found", "__handler_not_found"), ("wildcard", "__handler_wildcard")]; + + let page_exists = |key| match key { + "not_found" => file_exists!(&global!("dirs.handler", "/not_found")), + "wildcard" => file_exists!(&global!("dirs.handler", "/wildcard")), + _ => false, + }; + + for (page, handler) in fallback_routes { + if page_exists(page) { + if let Ok(route) = Route::get(handler).await { + return Some((route, vec![])); + } + } + } + + None +} + +async fn match_route(route_template: &str, placeholders: &Vec, url: &str) -> Option> { let mut matched_placeholders = Vec::new(); let route_segments: Vec<&str> = route_template.split('/').collect(); @@ -69,7 +89,7 @@ fn match_route(route_template: &str, placeholders: &[&str], url: &str) -> Option } for (route_segment, url_segment) in route_segments.iter().zip(url_segments.iter()) { - if let Some(placeholder_value) = match_segment(route_segment, url_segment, placeholders) { + if let Some(placeholder_value) = match_segment(route_segment, url_segment, placeholders).await { if !placeholder_value.is_empty() { matched_placeholders.push(placeholder_value); } @@ -81,9 +101,9 @@ fn match_route(route_template: &str, placeholders: &[&str], url: &str) -> Option Some(matched_placeholders) } -fn match_segment(route_segment: &str, url_segment: &str, placeholders: &[&str]) -> Option { +async fn match_segment<'a>(route_segment: &'a str, url_segment: &'a str, placeholders: &Vec) -> Option { if route_segment.starts_with('{') && route_segment.ends_with('}') { - let placeholder = &route_segment[1..route_segment.len() - 1]; + let placeholder = route_segment[1..route_segment.len() - 1].into(); if placeholders.contains(&placeholder) { Some(url_segment.to_string()) } else { @@ -95,7 +115,7 @@ fn match_segment(route_segment: &str, url_segment: &str, placeholders: &[&str]) let route_parts: Vec<&str> = route_segment.split('.').collect(); let url_parts: Vec<&str> = url_segment.split('.').collect(); if route_parts.len() == url_parts.len() && route_parts.last() == url_parts.last() { - match_segment(route_parts[0], url_parts[0], placeholders) + Box::pin(match_segment(route_parts[0], url_parts[0], placeholders)).await } else { None } @@ -105,6 +125,27 @@ fn match_segment(route_segment: &str, url_segment: &str, placeholders: &[&str]) impl Route { pub fn default() -> Self { Default::default() } + pub async fn search_for(url: &str) -> Option<(Route, Vec)> { + let index = ROUTES_INDEX.lock().await; + + for entry in index.iter() { + let (_, route_container) = entry.pair(); + let route_template = &route_container.inner.route; + + let placeholders = match &route_container.inner.args { + Some(args) => args, + None => &vec![], + }; + + if let Some(matched_values) = match_route(route_template, &placeholders, url).await { + println!("found: {url}"); + return Some((route_container.inner.clone(), matched_values)); + } + } + + get_fallback_route().await + } + pub async fn cleanup() -> std::io::Result<()> { let cache_dir = PathBuf::from(global!("base.cache")); let routes = ROUTES_INDEX.lock().await; @@ -246,32 +287,14 @@ impl Route { pub async fn get(key: &str) -> Result { let key = match key { "/" => global!("dirs.cache", "/index"), + "__handler_not_found" => global!("dirs.handler", "/not_found"), + "__handler_wildcard" => global!("dirs.handler", "/wildcard"), _ => global!("dirs.cache", key), }; - let files = HashMap::from([ - ("not_found", global!("dirs.handler", "/not_found")), - ("wildcard", global!("dirs.handler", "/wildcard")), - ("server_error", global!("dirs.handler", "/internal_err")), - ]); - - let page_exists = |key| match key { - "not_found" => file_exists!(&files.get("not_found").unwrap()), - "wildcard" => file_exists!(&files.get("wildcard").unwrap()), - _ => false, - }; - let bytes = match read(&key).await { Ok(contents) => contents, - Err(err) => { - if page_exists("not_found") { - read(files.get("not_found").unwrap()).await? - } else if page_exists("wildcard") { - read(files.get("wildcard").unwrap()).await? - } else { - return Err(anyhow!(err)); - } - } + Err(err) => return Err(anyhow!(err)), }; Ok(ron::de::from_bytes(&bytes)?) diff --git a/src/routes/match.rs b/src/routes/match.rs new file mode 100644 index 0000000..e69de29 -- GitLab