/* This file is part of gnix (https://codeberg.org/metamuffin/gnix) which is licensed under the GNU Affero General Public License (version 3); see /COPYING. Copyright (C) 2025 metamuffin */ 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_yml::Value) -> Result> { Ok(Arc::new(serde_yml::from_value::(config)?)) } } impl Node for Redirect { fn handle<'a>( &'a self, _context: &'a mut NodeContext, _request: NodeRequest, ) -> Pin> + 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(deserializer: D) -> std::result::Result 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}")))?, )) } }