summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormetamuffin <metamuffin@disroot.org>2024-06-22 13:05:21 +0200
committermetamuffin <metamuffin@disroot.org>2024-06-22 13:05:21 +0200
commitb28c5418b0635bf2fc3b0d18922df4ebb7cccd57 (patch)
treedbb99cde2eee412b1744bcc39827d31ce4e9606c
parent4da8fe84c07e3f9e83f9b769f1670f4d52466001 (diff)
downloadgnix-2.1.0.tar
gnix-2.1.0.tar.bz2
gnix-2.1.0.tar.zst
add redirect modulev2.1.0
-rw-r--r--readme.md4
-rw-r--r--src/modules/mod.rs3
-rw-r--r--src/modules/redirect.rs50
3 files changed, 57 insertions, 0 deletions
diff --git a/readme.md b/readme.md
index cef479e..428fabd 100644
--- a/readme.md
+++ b/readme.md
@@ -174,6 +174,10 @@ themselves; in that case the request is passed on.
- `headers`: A map of all header name-value pairs. (object string:string)
- `inner`: The handler to add the headers to. (module)
+- **module `redirect`**
+ - Responds with a permanent redirect.
+ - Takes the location to redirect to. (string)
+
#### Credentials config format
Login credentials for `cookie_auth` and `http_basic_auth` are supplied as either
diff --git a/src/modules/mod.rs b/src/modules/mod.rs
index 0fe9ca0..00425bf 100644
--- a/src/modules/mod.rs
+++ b/src/modules/mod.rs
@@ -12,6 +12,7 @@ use hosts::HostsKind;
use http_body_util::combinators::BoxBody;
use hyper::{body::Incoming, Request, Response};
use proxy::ProxyKind;
+use redirect::RedirectKind;
use serde_yaml::Value;
use std::{net::SocketAddr, pin::Pin, sync::Arc};
use switch::SwitchKind;
@@ -24,6 +25,7 @@ pub mod files;
pub mod headers;
pub mod hosts;
pub mod proxy;
+pub mod redirect;
pub mod switch;
pub type NodeRequest = Request<Incoming>;
@@ -40,6 +42,7 @@ pub static MODULES: &[&dyn NodeKind] = &[
&ErrorKind,
&HeadersKind,
&SwitchKind,
+ &RedirectKind,
];
pub struct NodeContext {
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}")))?,
+ ))
+ }
+}