From 8ba03054770591debdabb34229fcf83d9cc2b21d Mon Sep 17 00:00:00 2001 From: Ruslan Pislari Date: Tue, 5 May 2026 14:29:43 +0300 Subject: [PATCH 1/2] feat: add `Fastedge_Header_Hostname` header support and allow `Host` header overrides Added the `Fastedge_Header_Hostname` header for backend requests when the `Host` header is set. Updated the forbidden header policy to permit the `Host` header, improving backend request handling and compatibility. --- crates/http-service/src/state.rs | 36 ++++++++++++++++++++++---------- crates/runtime/src/lib.rs | 11 +++++++++- 2 files changed, 35 insertions(+), 12 deletions(-) diff --git a/crates/http-service/src/state.rs b/crates/http-service/src/state.rs index b15af1a..e780e00 100644 --- a/crates/http-service/src/state.rs +++ b/crates/http-service/src/state.rs @@ -17,6 +17,8 @@ pub struct HttpState { pub(super) stats: Arc, } +const FASTEDGE_HEADER_HOSTNAME: &[u8] = b"Fastedge_Header_Hostname"; + impl BackendRequest for HttpState { fn backend_request(&mut self, mut head: Parts) -> anyhow::Result { match self.http_backend.strategy { @@ -36,17 +38,23 @@ impl BackendRequest for HttpState { (_, Some(port)) => format!("{}:{}", a.host(), port), } }); - let original_host = original_host - .or_else(|| { - head.headers.iter().find_map(|(k, v)| { - if k.as_str().eq_ignore_ascii_case("host") { - v.to_str().ok().map(|c| c.to_string()) - } else { - None - } - }) - }) - .unwrap_or_default(); + let request_host_header_value = head + .headers + .iter() + .find(|(k, _)| k.eq(&header::HOST)) + .map(|(_, v)| v.to_owned()); + + let original_host = original_host.or_else(|| { + request_host_header_value + .as_ref() + .and_then(|v| v.to_str().map(|v| v.to_string()).ok()) + }); + + anyhow::ensure!( + original_host.is_some(), + "host is required for backend request" + ); + let original_host = original_host.unwrap(); anyhow::ensure!( is_public_host(&original_host), @@ -81,6 +89,12 @@ impl BackendRequest for HttpState { HeaderName::from_static("fastedge-scheme"), original_url.scheme_str().unwrap_or("http").parse()?, ); + //When HTTP app sets Host header, Fastegde needs to set Fastedge_Header_Hostname header for BE. + if let Some(request_host_header) = request_host_header_value { + let fastedge_header_hostname = + HeaderName::from_bytes(FASTEDGE_HEADER_HOSTNAME)?; + headers.insert(fastedge_header_hostname, request_host_header); + } headers.extend(self.propagate_headers.clone()); diff --git a/crates/runtime/src/lib.rs b/crates/runtime/src/lib.rs index ba1c6ee..eb49147 100644 --- a/crates/runtime/src/lib.rs +++ b/crates/runtime/src/lib.rs @@ -34,7 +34,7 @@ use crate::util::stats::StatsVisitor; use anyhow::{anyhow, bail}; pub use app::{App, SecretValue, SecretValues}; use http::request::Parts; -use http::Request; +use http::{header, HeaderName, Request}; use secret::SecretStore; use smol_str::SmolStr; use std::borrow::Cow; @@ -157,6 +157,15 @@ impl WasiHttpView for Data { fn table(&mut self) -> &mut ResourceTable { &mut self.table } + + fn is_forbidden_header(&mut self, name: &HeaderName) -> bool { + // We want to allow the host header to be set. + if name.eq(&header::HOST) { + return false; + } + // Fall back to wasmtime's default forbidden-header policy. + wasmtime_wasi_http::types::DEFAULT_FORBIDDEN_HEADERS.contains(name) + } } impl Data { From 8dc5cf2d1d8db0d5383a70ff6a2a580476e2c085 Mon Sep 17 00:00:00 2001 From: Ruslan Pislari Date: Tue, 5 May 2026 14:30:32 +0300 Subject: [PATCH 2/2] chore: Release --- CHANGELOG.md | 6 ++++++ Cargo.lock | 18 +++++++++--------- Cargo.toml | 2 +- 3 files changed, 16 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c36da35..b63f12d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ +## [0.16.1] - 2026-05-05 + +### 🚀 Features + +- Add `Fastedge_Header_Hostname` header support and allow `Host` header overrides ## [0.16.0] - 2026-05-05 ### 🚀 Features @@ -20,6 +25,7 @@ - Update dependencies in Cargo.lock and Cargo.toml to latest versions - Update Wasmtime dependency to use `component-model` feature +- Release ## [0.15.0] - 2026-03-10 ### 🚀 Features diff --git a/Cargo.lock b/Cargo.lock index 118498c..7ecf74e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -265,7 +265,7 @@ checksum = "6bd91ee7b2422bcb158d90ef4d14f75ef67f340943fc4149891dcce8f8b972a3" [[package]] name = "cache" -version = "0.16.0" +version = "0.16.1" dependencies = [ "async-trait", "reactor", @@ -962,7 +962,7 @@ dependencies = [ [[package]] name = "fastedge-run" -version = "0.16.0" +version = "0.16.1" dependencies = [ "anyhow", "async-trait", @@ -1557,7 +1557,7 @@ dependencies = [ [[package]] name = "http-backend" -version = "0.16.0" +version = "0.16.1" dependencies = [ "anyhow", "claims", @@ -1600,7 +1600,7 @@ dependencies = [ [[package]] name = "http-service" -version = "0.16.0" +version = "0.16.1" dependencies = [ "anyhow", "async-trait", @@ -1959,7 +1959,7 @@ dependencies = [ [[package]] name = "key-value-store" -version = "0.16.0" +version = "0.16.1" dependencies = [ "async-trait", "reactor", @@ -2800,7 +2800,7 @@ dependencies = [ [[package]] name = "reactor" -version = "0.16.0" +version = "0.16.1" dependencies = [ "wasmtime", ] @@ -2920,7 +2920,7 @@ dependencies = [ [[package]] name = "runtime" -version = "0.16.0" +version = "0.16.1" dependencies = [ "anyhow", "async-trait", @@ -3089,7 +3089,7 @@ checksum = "0cd08a21f852bd2fe42e3b2a6c76a0db6a95a5b5bd29c0521dd0b30fa1712ec8" [[package]] name = "secret" -version = "0.16.0" +version = "0.16.1" dependencies = [ "anyhow", "reactor", @@ -3838,7 +3838,7 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "utils" -version = "0.16.0" +version = "0.16.1" dependencies = [ "reactor", ] diff --git a/Cargo.toml b/Cargo.toml index 497d461..8313db4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,7 +3,7 @@ members = ["crates/*"] resolver = "2" [workspace.package] -version = "0.16.0" +version = "0.16.1" edition = "2021" publish = false authors = ["FastEdge Development Team"]