Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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
Expand Down
18 changes: 9 additions & 9 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"]
Expand Down
36 changes: 25 additions & 11 deletions crates/http-service/src/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ pub struct HttpState<C> {
pub(super) stats: Arc<dyn StatsVisitor>,
}

const FASTEDGE_HEADER_HOSTNAME: &[u8] = b"Fastedge_Header_Hostname";

impl<C> BackendRequest for HttpState<C> {
fn backend_request(&mut self, mut head: Parts) -> anyhow::Result<Parts> {
match self.http_backend.strategy {
Expand All @@ -36,17 +38,23 @@ impl<C> BackendRequest for HttpState<C> {
(_, 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();
Comment thread
ruslanti marked this conversation as resolved.

anyhow::ensure!(
is_public_host(&original_host),
Expand Down Expand Up @@ -81,6 +89,12 @@ impl<C> BackendRequest for HttpState<C> {
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.
Comment thread
ruslanti marked this conversation as resolved.
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);
Comment thread
ruslanti marked this conversation as resolved.
}

headers.extend(self.propagate_headers.clone());

Expand Down
11 changes: 10 additions & 1 deletion crates/runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -157,6 +157,15 @@ impl<T: Send + BackendRequest + HasStats> WasiHttpView for Data<T> {
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<T> Data<T> {
Expand Down
Loading