aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/error.rs2
-rw-r--r--src/modules/mod.rs2
-rw-r--r--src/modules/paths.rs54
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
+ })
+ }
+}