From 06e736c7947e3ae43779d8035542896a78227fa0 Mon Sep 17 00:00:00 2001 From: metamuffin Date: Sun, 14 Sep 2025 00:37:11 +0200 Subject: fix many things in upgrade_insecure module --- readme.md | 7 +++++++ src/modules/upgrade_insecure.rs | 25 ++++++++++++++++++------- 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/readme.md b/readme.md index fa7587a..384c3d7 100644 --- a/readme.md +++ b/readme.md @@ -301,6 +301,13 @@ themselves; in that case the request is passed on. - Replies with information about the request to debug. Includes source address, HTTP version, method, URI and headers. +- **module `upgrade_insecure`** + - Redirects requests from HTTP to HTTPS when `Upgrade-Insecure-Requests` is + present in the request. The redirect URI's authority will be the `Host` + header of the request. **Do not use behind another proxy** because requests + will always be HTTP and result in an endless redirect loop. + - Takes a single module (as a single-element array because of a parser limitation) + #### Credentials config format Login credentials for `cookie_auth` and `http_basic_auth` are supplied as either diff --git a/src/modules/upgrade_insecure.rs b/src/modules/upgrade_insecure.rs index e284df0..37fc04e 100644 --- a/src/modules/upgrade_insecure.rs +++ b/src/modules/upgrade_insecure.rs @@ -7,10 +7,13 @@ 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::{ + uri::{Authority, Scheme}, + HeaderValue, Response, StatusCode, Uri, +}; use http_body_util::BodyExt; use serde::Deserialize; -use std::{pin::Pin, sync::Arc}; +use std::{pin::Pin, str::FromStr, sync::Arc}; pub struct UpgradeInsecureKind; @@ -33,12 +36,20 @@ impl Node for UpgradeInsecure { request: NodeRequest, ) -> Pin> + Send + Sync + 'a>> { Box::pin(async move { - if request.headers().contains_key("upgrade-insecure-requests") - && request.uri().scheme() == Some(&Scheme::HTTP) - { + if request.headers().contains_key("upgrade-insecure-requests") && !context.secure { let mut parts = http::uri::Parts::default(); - parts.scheme = request.uri().scheme().cloned(); - parts.authority = request.uri().authority().cloned(); + parts.scheme = Some(Scheme::HTTPS); + parts.authority = Some( + Authority::from_str( + request + .headers() + .get("host") + .ok_or(ServiceError::NoHost)? + .to_str() + .map_err(|_| ServiceError::InvalidUri)?, + ) + .map_err(|_| ServiceError::InvalidUri)?, + ); parts.path_and_query = request.uri().path_and_query().cloned(); let uri = Uri::from_parts(parts).map_err(|_| ServiceError::InvalidUri)?; -- cgit v1.2.3-70-g09d2