From 6c3524c381467483a025eda5e7e5f0ded53094fa Mon Sep 17 00:00:00 2001 From: metamuffin Date: Mon, 19 Aug 2024 02:52:14 +0200 Subject: paths module --- src/error.rs | 2 ++ src/modules/mod.rs | 2 ++ src/modules/paths.rs | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 58 insertions(+) create mode 100644 src/modules/paths.rs (limited to 'src') 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, +} + +impl NodeKind for PathsKind { + fn name(&self) -> &'static str { + "paths" + } + fn instanciate(&self, config: Value) -> anyhow::Result> { + let routes = serde_yaml::from_value::>(config)? + .into_iter() + .collect::>(); + + 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> + 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 + }) + } +} -- cgit v1.2.3-70-g09d2