diff options
Diffstat (limited to 'src/modules/redirect.rs')
-rw-r--r-- | src/modules/redirect.rs | 50 |
1 files changed, 50 insertions, 0 deletions
diff --git a/src/modules/redirect.rs b/src/modules/redirect.rs new file mode 100644 index 0000000..e3fa599 --- /dev/null +++ b/src/modules/redirect.rs @@ -0,0 +1,50 @@ +use super::{Node, NodeContext, NodeKind, NodeRequest, NodeResponse}; +use crate::error::ServiceError; +use anyhow::Result; +use futures::Future; +use http_body_util::BodyExt; +use hyper::{header::HeaderValue, Response, StatusCode}; +use serde::Deserialize; +use std::{pin::Pin, sync::Arc}; + +pub struct RedirectKind; + +#[derive(Deserialize)] +pub struct Redirect(HeaderValueWrap); + +impl NodeKind for RedirectKind { + fn name(&self) -> &'static str { + "redirect" + } + fn instanciate(&self, config: serde_yaml::Value) -> Result<Arc<dyn Node>> { + Ok(Arc::new(serde_yaml::from_value::<Redirect>(config)?)) + } +} + +impl Node for Redirect { + 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 mut resp = Response::new("".to_string()).map(|b| b.map_err(|e| match e {}).boxed()); + *resp.status_mut() = StatusCode::MOVED_PERMANENTLY; + resp.headers_mut().insert("Location", self.0 .0.clone()); + Ok(resp) + }) + } +} + +struct HeaderValueWrap(HeaderValue); +impl<'de> Deserialize<'de> for HeaderValueWrap { + fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error> + where + D: serde::Deserializer<'de>, + { + let s = String::deserialize(deserializer)?; + Ok(HeaderValueWrap( + HeaderValue::from_str(&s).map_err(|e| serde::de::Error::custom(format!("{e}")))?, + )) + } +} |