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 }) } }