diff options
author | metamuffin <metamuffin@disroot.org> | 2024-11-11 22:21:42 +0100 |
---|---|---|
committer | metamuffin <metamuffin@disroot.org> | 2024-11-11 22:21:42 +0100 |
commit | cc5d7c08cca9cb4a14f1f99355262b9b3ff04b0c (patch) | |
tree | 4c4855ccf22b0a944ea312e880c71a643cf88087 | |
parent | 3f6ec191b38b4c60ac2d42ab941b4690f42f7c21 (diff) | |
download | gnix-cc5d7c08cca9cb4a14f1f99355262b9b3ff04b0c.tar gnix-cc5d7c08cca9cb4a14f1f99355262b9b3ff04b0c.tar.bz2 gnix-cc5d7c08cca9cb4a14f1f99355262b9b3ff04b0c.tar.zst |
implement insecure connection upgrade. yaml parser broken
-rw-r--r-- | src/modules/mod.rs | 32 | ||||
-rw-r--r-- | src/modules/upgrade_insecure.rs | 58 |
2 files changed, 75 insertions, 15 deletions
diff --git a/src/modules/mod.rs b/src/modules/mod.rs index 288158c..7470725 100644 --- a/src/modules/mod.rs +++ b/src/modules/mod.rs @@ -7,21 +7,22 @@ use hyper::{body::Incoming, Request, Response}; use serde_yml::Value; use std::{net::SocketAddr, pin::Pin, sync::Arc}; -pub mod accesslog; -pub mod auth; -pub mod cache; -pub mod cgi; -pub mod debug; -pub mod error; -pub mod file; -pub mod files; -pub mod headers; -pub mod hosts; -pub mod loadbalance; -pub mod paths; -pub mod proxy; -pub mod redirect; -pub mod switch; +mod accesslog; +mod auth; +mod cache; +mod cgi; +mod debug; +mod error; +mod file; +mod files; +mod headers; +mod hosts; +mod loadbalance; +mod paths; +mod proxy; +mod redirect; +mod switch; +mod upgrade_insecure; pub type NodeRequest = Request<Incoming>; pub type NodeResponse = Response<BoxBody<Bytes, ServiceError>>; @@ -44,6 +45,7 @@ pub static MODULES: &[&dyn NodeKind] = &[ &debug::DebugKind, &cache::CacheKind, &loadbalance::LoadBalanceKind, + &upgrade_insecure::UpgradeInsecureKind, ]; pub struct NodeContext { diff --git a/src/modules/upgrade_insecure.rs b/src/modules/upgrade_insecure.rs new file mode 100644 index 0000000..c201d96 --- /dev/null +++ b/src/modules/upgrade_insecure.rs @@ -0,0 +1,58 @@ +use super::{Node, NodeContext, NodeKind, NodeRequest, NodeResponse}; +use crate::{config::DynNode, error::ServiceError}; +use anyhow::Result; +use futures::Future; +use http::{uri::Scheme, HeaderValue, Response, StatusCode, Uri}; +use http_body_util::BodyExt; +use serde::Deserialize; +use serde_yml::with::singleton_map_recursive; +use std::{pin::Pin, sync::Arc}; + +pub struct UpgradeInsecureKind; + +#[derive(Deserialize)] +pub struct UpgradeInsecure(DynNode); + +impl NodeKind for UpgradeInsecureKind { + fn name(&self) -> &'static str { + "upgrade_insecure" + } + fn instanciate(&self, config: serde_yml::Value) -> Result<Arc<dyn Node>> { + Ok(Arc::new(serde_yml::from_value::<UpgradeInsecure>(config)?)) + } +} + +impl Node for UpgradeInsecure { + 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 { + if request.headers().contains_key("upgrade-insecure-requests") + && request.uri().scheme() == Some(&Scheme::HTTP) + { + let mut parts = http::uri::Parts::default(); + parts.scheme = request.uri().scheme().cloned(); + parts.authority = request.uri().authority().cloned(); + parts.path_and_query = request.uri().path_and_query().cloned(); + let uri = Uri::from_parts(parts).map_err(|_| ServiceError::InvalidUri)?; + + 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", + HeaderValue::from_str(&uri.to_string()) + .map_err(|_| ServiceError::InvalidUri)?, + ); + resp.headers_mut().insert( + "Vary", + HeaderValue::from_static("Upgrade-Insecure-Requests"), + ); + return Ok(resp); + } + self.0.handle(context, request).await + }) + } +} |