summaryrefslogtreecommitdiff
path: root/src/modules/fallback.rs
diff options
context:
space:
mode:
authormetamuffin <metamuffin@disroot.org>2025-02-05 12:45:56 +0100
committermetamuffin <metamuffin@disroot.org>2025-02-05 12:45:56 +0100
commit27a503c1a92c8f8b0e398187d58e677ecf68e915 (patch)
tree505393926d7208dd3e5c9acd923f140b6a60259a /src/modules/fallback.rs
parent65ceb5683340726ff2ee831181dd9d60da2456b3 (diff)
downloadgnix-27a503c1a92c8f8b0e398187d58e677ecf68e915.tar
gnix-27a503c1a92c8f8b0e398187d58e677ecf68e915.tar.bz2
gnix-27a503c1a92c8f8b0e398187d58e677ecf68e915.tar.zst
fallback handler
Diffstat (limited to 'src/modules/fallback.rs')
-rw-r--r--src/modules/fallback.rs61
1 files changed, 61 insertions, 0 deletions
diff --git a/src/modules/fallback.rs b/src/modules/fallback.rs
new file mode 100644
index 0000000..b0deed1
--- /dev/null
+++ b/src/modules/fallback.rs
@@ -0,0 +1,61 @@
+use super::{Node, NodeContext, NodeKind, NodeRequest, NodeResponse};
+use crate::{config::DynNode, error::ServiceError};
+use anyhow::Result;
+use http::Request;
+use http_body_util::{combinators::BoxBody, BodyExt, Full};
+use serde::Deserialize;
+use serde_yml::Value;
+use std::{future::Future, pin::Pin, sync::Arc};
+
+pub struct FallbackKind;
+
+#[derive(Deserialize)]
+struct Fallback(Vec<DynNode>);
+
+impl NodeKind for FallbackKind {
+ fn name(&self) -> &'static str {
+ "fallback"
+ }
+ fn instanciate(&self, config: Value) -> Result<Arc<dyn Node>> {
+ Ok(Arc::new(serde_yml::from_value::<Fallback>(config)?))
+ }
+}
+impl Node for Fallback {
+ 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 (parts, body) = request.into_parts();
+ let body = body
+ .collect()
+ .await
+ .map_err(|_| ServiceError::Other)?
+ .to_bytes();
+
+ for (i, h) in self.0.iter().enumerate() {
+ let last = i == self.0.len() - 1;
+ let resp = h
+ .handle(
+ context,
+ Request::from_parts(
+ parts.clone(),
+ BoxBody::new(Full::new(body.clone()).map_err(|x| match x {})),
+ ),
+ )
+ .await?;
+ if resp.status().is_success()
+ || resp.status().is_redirection()
+ || resp.status().is_informational()
+ || last
+ {
+ return Ok(resp);
+ }
+ }
+ return Err(ServiceError::CustomStatic(
+ "fallback module without any handlers",
+ ));
+ })
+ }
+}