diff options
author | metamuffin <metamuffin@disroot.org> | 2024-08-19 02:52:14 +0200 |
---|---|---|
committer | metamuffin <metamuffin@disroot.org> | 2024-08-19 02:52:14 +0200 |
commit | 6c3524c381467483a025eda5e7e5f0ded53094fa (patch) | |
tree | 0d081ed4bc18f0a950783a5fe8e1fe4e08c888d1 /src | |
parent | b005bbca6d8c1adb9c12e10d79028717b9d963c5 (diff) | |
download | gnix-6c3524c381467483a025eda5e7e5f0ded53094fa.tar gnix-6c3524c381467483a025eda5e7e5f0ded53094fa.tar.bz2 gnix-6c3524c381467483a025eda5e7e5f0ded53094fa.tar.zst |
paths module
Diffstat (limited to 'src')
-rw-r--r-- | src/error.rs | 2 | ||||
-rw-r--r-- | src/modules/mod.rs | 2 | ||||
-rw-r--r-- | src/modules/paths.rs | 54 |
3 files changed, 58 insertions, 0 deletions
diff --git a/src/error.rs b/src/error.rs index 14b2842..e6f7646 100644 --- a/src/error.rs +++ b/src/error.rs @@ -12,6 +12,8 @@ pub enum ServiceError { NoHost, #[error("unknown host")] UnknownHost, + #[error("unknown path")] + UnknownPath, #[error("can't connect to the backend")] CantConnect, #[error("not found")] diff --git a/src/modules/mod.rs b/src/modules/mod.rs index 987646f..dfb1f02 100644 --- a/src/modules/mod.rs +++ b/src/modules/mod.rs @@ -15,6 +15,7 @@ pub mod file; pub mod files; pub mod headers; pub mod hosts; +pub mod paths; pub mod proxy; pub mod redirect; pub mod switch; @@ -27,6 +28,7 @@ pub static MODULES: &[&dyn NodeKind] = &[ &auth::cookie::CookieAuthKind, &proxy::ProxyKind, &hosts::HostsKind, + &paths::PathsKind, &files::FilesKind, &file::FileKind, &accesslog::AccessLogKind, diff --git a/src/modules/paths.rs b/src/modules/paths.rs new file mode 100644 index 0000000..b994d48 --- /dev/null +++ b/src/modules/paths.rs @@ -0,0 +1,54 @@ +use super::{Node, NodeContext, NodeKind, NodeRequest, NodeResponse}; +use crate::{config::DynNode, error::ServiceError}; +use futures::Future; +use regex::RegexSet; +use serde_yaml::Value; +use std::{collections::BTreeMap, pin::Pin, sync::Arc}; + +pub struct PathsKind; + +struct Paths { + matcher: RegexSet, + handlers: Vec<DynNode>, +} + +impl NodeKind for PathsKind { + fn name(&self) -> &'static str { + "paths" + } + fn instanciate(&self, config: Value) -> anyhow::Result<Arc<dyn Node>> { + let routes = serde_yaml::from_value::<BTreeMap<String, DynNode>>(config)? + .into_iter() + .collect::<Vec<(String, DynNode)>>(); + + let mut handlers = Vec::new(); + let mut patterns = Vec::new(); + for (k, v) in routes { + handlers.push(v); + patterns.push(format!("^{}$", k)); + } + let matcher = RegexSet::new(&patterns)?; + + Ok(Arc::new(Paths { handlers, matcher })) + } +} +impl Node for Paths { + fn handle<'a>( + &'a self, + context: &'a mut NodeContext, + request: NodeRequest, + ) -> Pin<Box<dyn Future<Output = Result<NodeResponse, ServiceError>> + Send + Sync + 'a>> { + Box::pin(async move { + let path = request.uri().path(); + + let index = self + .matcher + .matches(path) + .iter() + .next() + .ok_or(ServiceError::UnknownPath)?; + + self.handlers[index].handle(context, request).await + }) + } +} |