From 25230a320cc655e917fd7c29cc3f79c377d7c3a8 Mon Sep 17 00:00:00 2001 From: Christian Date: Thu, 29 Jan 2026 11:25:34 -0600 Subject: [PATCH 1/4] fix: dynamic backends only connecting over http --- crates/edgezero-adapter-fastly/src/proxy.rs | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/crates/edgezero-adapter-fastly/src/proxy.rs b/crates/edgezero-adapter-fastly/src/proxy.rs index 170b5b0..08f19cd 100644 --- a/crates/edgezero-adapter-fastly/src/proxy.rs +++ b/crates/edgezero-adapter-fastly/src/proxy.rs @@ -105,14 +105,23 @@ fn ensure_backend(uri: &Uri) -> Result { None => host.to_string(), }; - let builder = Backend::builder(&name, &host_with_port).override_host(host); + let mut builder = Backend::builder(&name, &host_with_port).override_host(host); + if uri.scheme_str() == Some("https") { + builder = builder + .enable_ssl() + .sni_hostname(host) + .check_certificate(host); + } match builder.finish() { Ok(backend) => Ok(backend), Err(_) => { let mut builder = Backend::builder(&name, &target); if uri.scheme_str() == Some("https") { - builder = builder.enable_ssl(); + builder = builder + .enable_ssl() + .sni_hostname(host) + .check_certificate(host); } builder.finish().map_err(EdgeError::internal) } From 20f89ad6eef8a7d361ae1bbcddf419f1edfbae47 Mon Sep 17 00:00:00 2001 From: Christian Date: Thu, 5 Feb 2026 13:55:10 -0600 Subject: [PATCH 2/4] brings ensure_backend in line with trusted servers function --- crates/edgezero-adapter-fastly/src/proxy.rs | 79 ++++++++++++--------- 1 file changed, 46 insertions(+), 33 deletions(-) diff --git a/crates/edgezero-adapter-fastly/src/proxy.rs b/crates/edgezero-adapter-fastly/src/proxy.rs index 08f19cd..df736c4 100644 --- a/crates/edgezero-adapter-fastly/src/proxy.rs +++ b/crates/edgezero-adapter-fastly/src/proxy.rs @@ -10,9 +10,8 @@ use fastly::{ http::body::StreamingBody, Backend, Request as FastlyRequest, Response as FastlyResponse, }; use futures_util::stream::{BoxStream, StreamExt}; -use std::collections::hash_map::DefaultHasher; -use std::hash::{Hash, Hasher}; use std::io::{self, Write}; +use std::time::Duration; const BACKEND_PREFIX: &str = "edgezero-dynamic-"; @@ -22,10 +21,10 @@ pub struct FastlyProxyClient; impl ProxyClient for FastlyProxyClient { async fn send(&self, request: ProxyRequest) -> Result { let (method, uri, headers, body, _ext) = request.into_parts(); - let backend = ensure_backend(&uri)?; + let backend_name = ensure_backend(&uri)?; let fastly_request = build_fastly_request(method, &uri, headers)?; let (mut streaming_body, pending_request) = fastly_request - .send_async_streaming(backend.name()) + .send_async_streaming(&backend_name) .map_err(EdgeError::internal)?; forward_request_body(body, &mut streaming_body).await?; streaming_body.finish().map_err(EdgeError::internal)?; @@ -88,54 +87,68 @@ async fn forward_request_body( Ok(()) } -fn ensure_backend(uri: &Uri) -> Result { +fn ensure_backend(uri: &Uri) -> Result { let host = uri .host() .ok_or_else(|| EdgeError::bad_request("proxy target must include host"))?; - let port = uri.port_u16(); - let target = match port { - Some(port) => format!("{}:{}", host, port), - None => host.to_string(), - }; - let name = backend_name(&target, uri.scheme_str()); + let scheme = uri.scheme_str().unwrap_or("https"); + let is_https = scheme.eq_ignore_ascii_case("https"); - let host_with_port = match port { - Some(p) => format!("{}:{}", host, p), - None => host.to_string(), + let target_port = match (uri.port_u16(), is_https) { + (Some(p), _) => p, + (None, true) => 443, + (None, false) => 80, }; - let mut builder = Backend::builder(&name, &host_with_port).override_host(host); - if uri.scheme_str() == Some("https") { + let host_with_port = format!("{}:{}", host, target_port); + + // Human-readable name: backend_{scheme}_{host}_{port} with dots/colons sanitised + let name_base = format!("{}_{}_{}", scheme, host, target_port); + let backend_name = format!( + "{}{}", + BACKEND_PREFIX, + name_base.replace(['.', ':'], "_") + ); + + let mut builder = Backend::builder(&backend_name, &host_with_port) + .override_host(host) + .connect_timeout(Duration::from_secs(1)) + .first_byte_timeout(Duration::from_secs(15)) + .between_bytes_timeout(Duration::from_secs(10)); + + if is_https { builder = builder .enable_ssl() .sni_hostname(host) .check_certificate(host); + log::info!("enable ssl for backend: {}", backend_name); } match builder.finish() { - Ok(backend) => Ok(backend), - Err(_) => { - let mut builder = Backend::builder(&name, &target); - if uri.scheme_str() == Some("https") { - builder = builder - .enable_ssl() - .sni_hostname(host) - .check_certificate(host); + Ok(_) => { + log::info!( + "created dynamic backend: {} -> {}", + backend_name, + host_with_port + ); + Ok(backend_name) + } + Err(e) => { + let msg = e.to_string(); + if msg.contains("NameInUse") || msg.contains("already in use") { + log::info!("reusing existing dynamic backend: {}", backend_name); + Ok(backend_name) + } else { + Err(EdgeError::internal(format!( + "dynamic backend creation failed ({} -> {}): {}", + backend_name, host_with_port, msg + ))) } - builder.finish().map_err(EdgeError::internal) } } } -fn backend_name(target: &str, scheme: Option<&str>) -> String { - let mut hasher = DefaultHasher::new(); - target.hash(&mut hasher); - scheme.hash(&mut hasher); - let hash = hasher.finish(); - format!("{}{:016x}", BACKEND_PREFIX, hash) -} - fn convert_response(fastly_response: &mut FastlyResponse) -> Result { let status = fastly_response.get_status(); let mut proxy_response = ProxyResponse::new(status, Body::empty()); From b392ab7f8d4a7faad0a3167c64cced6a7878c662 Mon Sep 17 00:00:00 2001 From: Christian Date: Thu, 5 Feb 2026 14:01:06 -0600 Subject: [PATCH 3/4] change logs to debug --- crates/edgezero-adapter-fastly/src/proxy.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/edgezero-adapter-fastly/src/proxy.rs b/crates/edgezero-adapter-fastly/src/proxy.rs index df736c4..9b5e611 100644 --- a/crates/edgezero-adapter-fastly/src/proxy.rs +++ b/crates/edgezero-adapter-fastly/src/proxy.rs @@ -122,12 +122,12 @@ fn ensure_backend(uri: &Uri) -> Result { .enable_ssl() .sni_hostname(host) .check_certificate(host); - log::info!("enable ssl for backend: {}", backend_name); + log::debug!("enable ssl for backend: {}", backend_name); } match builder.finish() { Ok(_) => { - log::info!( + log::debug!( "created dynamic backend: {} -> {}", backend_name, host_with_port @@ -137,7 +137,7 @@ fn ensure_backend(uri: &Uri) -> Result { Err(e) => { let msg = e.to_string(); if msg.contains("NameInUse") || msg.contains("already in use") { - log::info!("reusing existing dynamic backend: {}", backend_name); + log::debug!("reusing existing dynamic backend: {}", backend_name); Ok(backend_name) } else { Err(EdgeError::internal(format!( From db6f1e478fe2bf36c10137758330bdd0342d10ee Mon Sep 17 00:00:00 2001 From: Christian Date: Thu, 5 Feb 2026 14:50:29 -0600 Subject: [PATCH 4/4] fix compile error --- crates/edgezero-adapter-fastly/src/proxy.rs | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/crates/edgezero-adapter-fastly/src/proxy.rs b/crates/edgezero-adapter-fastly/src/proxy.rs index 9b5e611..24bdf55 100644 --- a/crates/edgezero-adapter-fastly/src/proxy.rs +++ b/crates/edgezero-adapter-fastly/src/proxy.rs @@ -7,7 +7,8 @@ use edgezero_core::error::EdgeError; use edgezero_core::http::{header, HeaderMap, HeaderValue, Method, Uri}; use edgezero_core::proxy::{ProxyClient, ProxyRequest, ProxyResponse}; use fastly::{ - http::body::StreamingBody, Backend, Request as FastlyRequest, Response as FastlyResponse, + error::anyhow, http::body::StreamingBody, Backend, Request as FastlyRequest, + Response as FastlyResponse, }; use futures_util::stream::{BoxStream, StreamExt}; use std::io::{self, Write}; @@ -105,11 +106,7 @@ fn ensure_backend(uri: &Uri) -> Result { // Human-readable name: backend_{scheme}_{host}_{port} with dots/colons sanitised let name_base = format!("{}_{}_{}", scheme, host, target_port); - let backend_name = format!( - "{}{}", - BACKEND_PREFIX, - name_base.replace(['.', ':'], "_") - ); + let backend_name = format!("{}{}", BACKEND_PREFIX, name_base.replace(['.', ':'], "_")); let mut builder = Backend::builder(&backend_name, &host_with_port) .override_host(host) @@ -140,9 +137,11 @@ fn ensure_backend(uri: &Uri) -> Result { log::debug!("reusing existing dynamic backend: {}", backend_name); Ok(backend_name) } else { - Err(EdgeError::internal(format!( + Err(EdgeError::internal(anyhow!( "dynamic backend creation failed ({} -> {}): {}", - backend_name, host_with_port, msg + backend_name, + host_with_port, + msg ))) } }