From 93ef9e640d304352b30acf4ad955138b8df6e266 Mon Sep 17 00:00:00 2001 From: Christian Date: Mon, 13 Oct 2025 11:02:56 -0500 Subject: [PATCH 1/4] Replaces local, fastly backend config with dynamic backends. Only required config is origin_url. Origin backend is deprecated. --- crates/common/src/publisher.rs | 31 ++++++++++++++++++++++++------- crates/common/src/settings.rs | 1 + fastly.toml | 4 ---- trusted-server.toml | 1 + 4 files changed, 26 insertions(+), 11 deletions(-) diff --git a/crates/common/src/publisher.rs b/crates/common/src/publisher.rs index fcac4e4..a7f5473 100644 --- a/crates/common/src/publisher.rs +++ b/crates/common/src/publisher.rs @@ -1,7 +1,9 @@ use error_stack::{Report, ResultExt}; use fastly::http::{header, StatusCode}; use fastly::{Body, Request, Response}; +use url::Url; +use crate::backend::ensure_origin_backend; use crate::http_util::serve_static_with_etag; use crate::constants::{ @@ -359,17 +361,32 @@ pub fn handle_publisher_request( has_synthetic_cookie ); - // Extract host from the origin_url using the Publisher's origin_host method - let origin_host = settings.publisher.origin_host(); + let parsed_url = + Url::parse(&settings.publisher.origin_url).change_context(TrustedServerError::Proxy { + message: format!("Invalid origin_url: {}", settings.publisher.origin_url), + })?; + + let scheme = parsed_url.scheme(); + let origin_host = parsed_url.host_str().ok_or_else(|| { + Report::new(TrustedServerError::Proxy { + message: "Missing host in origin_url".to_string(), + }) + })?; + let port = parsed_url.port(); - log::info!("Setting host header to: {}", origin_host); - req.set_header("host", &origin_host); + let backend_name = ensure_origin_backend(scheme, origin_host, port)?; + + log::info!( + "Proxying to dynamic backend: {} (from {})", + backend_name, + settings.publisher.origin_url + ); + req.set_header("host", origin_host); - // Send the request to the origin backend let mut response = req - .send(&settings.publisher.origin_backend) + .send(&backend_name) .change_context(TrustedServerError::Proxy { - message: "Failed to proxy request".to_string(), + message: "Failed to proxy request to origin".to_string(), })?; // Log all response headers for debugging diff --git a/crates/common/src/settings.rs b/crates/common/src/settings.rs index af34cf6..eff0a17 100644 --- a/crates/common/src/settings.rs +++ b/crates/common/src/settings.rs @@ -21,6 +21,7 @@ pub struct AdServer { pub struct Publisher { pub domain: String, pub cookie_domain: String, + #[deprecated(note = "Use origin_url instead - dynamic backends are created automatically")] pub origin_backend: String, pub origin_url: String, /// Secret used to encrypt/decrypt proxied URLs in `/first-party/proxy`. diff --git a/fastly.toml b/fastly.toml index d15cffe..0b00ed4 100644 --- a/fastly.toml +++ b/fastly.toml @@ -67,10 +67,6 @@ build = """ [local_server.backends.googleads_doubleclick_backend] url = "https://securepubads.g.doubleclick.net" - [local_server.backends.publisher_origin] - url = "http://localhost:9090" - override_host = "localhost:9090" - # Backend for proxying ad creatives and tracking pixels [local_server.backends.ad_cdn_backend] url = "https://cdn.adsrvr.org" # Default, will be overridden dynamically diff --git a/trusted-server.toml b/trusted-server.toml index 507a1ce..47b4fb0 100644 --- a/trusted-server.toml +++ b/trusted-server.toml @@ -5,6 +5,7 @@ sync_url = "https://adapi-srv-eu.smartadserver.com/ac?pgid=2040327&fmtid=137675& [publisher] domain = "test-publisher.com" cookie_domain = ".test-publisher.com" +# DEPRECATED origin backend is now dynamically created origin_backend = "publisher_origin" origin_url = "https://origin.test-publisher.com" proxy_secret = "change-me-proxy-secret" From 21109bedf7134913d99376a9ee0989f9462b4169 Mon Sep 17 00:00:00 2001 From: Christian Date: Mon, 13 Oct 2025 13:00:01 -0500 Subject: [PATCH 2/4] Removes prebid config for dynamic prebid backend --- crates/common/src/backend.rs | 18 +++++++++++++++++- crates/common/src/prebid.rs | 14 +++++++++++--- crates/common/src/prebid_proxy.rs | 10 ++++++++-- crates/common/src/publisher.rs | 21 ++++----------------- fastly.toml | 3 +-- 5 files changed, 41 insertions(+), 25 deletions(-) diff --git a/crates/common/src/backend.rs b/crates/common/src/backend.rs index 8818f0f..cb49ccf 100644 --- a/crates/common/src/backend.rs +++ b/crates/common/src/backend.rs @@ -1,7 +1,8 @@ use std::time::Duration; -use error_stack::Report; +use error_stack::{Report, ResultExt}; use fastly::backend::Backend; +use url::Url; use crate::error::TrustedServerError; @@ -66,6 +67,21 @@ pub fn ensure_origin_backend( } } } +pub fn ensure_backend_from_url(origin_url: &str) -> Result> { + let parsed_url = Url::parse(origin_url).change_context(TrustedServerError::Proxy { + message: format!("Invalid origin_url: {}", origin_url), + })?; + + let scheme = parsed_url.scheme(); + let host = parsed_url.host_str().ok_or_else(|| { + Report::new(TrustedServerError::Proxy { + message: "Missing host in origin_url".to_string(), + }) + })?; + let port = parsed_url.port(); + + ensure_origin_backend(scheme, host, port) +} #[cfg(test)] mod tests { diff --git a/crates/common/src/prebid.rs b/crates/common/src/prebid.rs index dd89674..d1a486f 100644 --- a/crates/common/src/prebid.rs +++ b/crates/common/src/prebid.rs @@ -8,6 +8,7 @@ use fastly::http::{header, Method, StatusCode}; use fastly::{Error, Request, Response}; use serde_json::json; +use crate::backend::ensure_backend_from_url; use crate::constants::{ HEADER_SYNTHETIC_FRESH, HEADER_SYNTHETIC_TRUSTED_SERVER, HEADER_X_COMPRESS_HINT, HEADER_X_CONSENT_ADVERTISING, HEADER_X_FORWARDED_FOR, @@ -194,10 +195,17 @@ impl PrebidRequest { id ); - req.set_body_json(&prebid_body)?; + // TrustedServerError doesn't implement std::error::Error + match ensure_backend_from_url(&settings.prebid.server_url) { + Ok(backend_name) => { + req.set_body_json(&prebid_body)?; - let resp = req.send("prebid_backend")?; - Ok(resp) + let resp = req.send(backend_name)?; + Ok(resp) + } + + Err(e) => fastly::error::bail!("Could not get prebid backend: {}", e), + } } } diff --git a/crates/common/src/prebid_proxy.rs b/crates/common/src/prebid_proxy.rs index 0159136..180dbf7 100644 --- a/crates/common/src/prebid_proxy.rs +++ b/crates/common/src/prebid_proxy.rs @@ -9,6 +9,7 @@ use fastly::http::{header, Method, StatusCode}; use fastly::{Request, Response}; use serde_json::{json, Value}; +use crate::backend::ensure_backend_from_url; use crate::constants::{HEADER_SYNTHETIC_FRESH, HEADER_SYNTHETIC_TRUSTED_SERVER}; use crate::error::TrustedServerError; use crate::gdpr::get_consent_from_request; @@ -78,10 +79,12 @@ pub async fn handle_prebid_auction( log::info!("Sending request to Prebid Server"); + let backend_name = ensure_backend_from_url(&settings.prebid.server_url)?; + // 5. Send to PBS and get response let mut pbs_response = pbs_req - .send("prebid_backend") + .send(backend_name) .change_context(TrustedServerError::Prebid { message: "Failed to send request to Prebid Server".to_string(), })?; @@ -175,9 +178,12 @@ pub async fn handle_prebid_cookie_sync( })?; // 4. Get response and transform sync URLs + + let backend_name = ensure_backend_from_url(&settings.prebid.server_url)?; + let mut pbs_response = pbs_req - .send("prebid_backend") + .send(backend_name) .change_context(TrustedServerError::Prebid { message: "Failed to send cookie sync request".to_string(), })?; diff --git a/crates/common/src/publisher.rs b/crates/common/src/publisher.rs index a7f5473..6fda0a3 100644 --- a/crates/common/src/publisher.rs +++ b/crates/common/src/publisher.rs @@ -1,9 +1,8 @@ use error_stack::{Report, ResultExt}; use fastly::http::{header, StatusCode}; use fastly::{Body, Request, Response}; -use url::Url; -use crate::backend::ensure_origin_backend; +use crate::backend::ensure_backend_from_url; use crate::http_util::serve_static_with_etag; use crate::constants::{ @@ -361,27 +360,15 @@ pub fn handle_publisher_request( has_synthetic_cookie ); - let parsed_url = - Url::parse(&settings.publisher.origin_url).change_context(TrustedServerError::Proxy { - message: format!("Invalid origin_url: {}", settings.publisher.origin_url), - })?; - - let scheme = parsed_url.scheme(); - let origin_host = parsed_url.host_str().ok_or_else(|| { - Report::new(TrustedServerError::Proxy { - message: "Missing host in origin_url".to_string(), - }) - })?; - let port = parsed_url.port(); - - let backend_name = ensure_origin_backend(scheme, origin_host, port)?; + let backend_name = ensure_backend_from_url(&settings.publisher.origin_url)?; + let origin_host = settings.publisher.origin_host(); log::info!( "Proxying to dynamic backend: {} (from {})", backend_name, settings.publisher.origin_url ); - req.set_header("host", origin_host); + req.set_header("host", &origin_host); let mut response = req .send(&backend_name) diff --git a/fastly.toml b/fastly.toml index 0b00ed4..c3729c5 100644 --- a/fastly.toml +++ b/fastly.toml @@ -44,8 +44,7 @@ build = """ [local_server.backends.equativ_ad_api_2] url = "https://adapi-srv-eu.smartadserver.com" - [local_server.backends.prebid_backend] - url = "http://68.183.113.79:8000" + [local_server.backends.gam_backend] url = "https://securepubads.g.doubleclick.net" [local_server.backends.wordpress_backend] From 5c2c5953f1e558a7dd3e9cc37e283950e6724da3 Mon Sep 17 00:00:00 2001 From: Christian Date: Mon, 13 Oct 2025 13:31:59 -0500 Subject: [PATCH 3/4] completely removes origin_backend setting --- crates/common/src/settings.rs | 9 --------- trusted-server.toml | 2 -- 2 files changed, 11 deletions(-) diff --git a/crates/common/src/settings.rs b/crates/common/src/settings.rs index eff0a17..3b59a1f 100644 --- a/crates/common/src/settings.rs +++ b/crates/common/src/settings.rs @@ -21,8 +21,6 @@ pub struct AdServer { pub struct Publisher { pub domain: String, pub cookie_domain: String, - #[deprecated(note = "Use origin_url instead - dynamic backends are created automatically")] - pub origin_backend: String, pub origin_url: String, /// Secret used to encrypt/decrypt proxied URLs in `/first-party/proxy`. /// Keep this secret stable to allow existing links to decode. @@ -39,7 +37,6 @@ impl Publisher { /// let publisher = Publisher { /// domain: "example.com".to_string(), /// cookie_domain: ".example.com".to_string(), - /// origin_backend: "edgepubs_main_be".to_string(), /// origin_url: "https://origin.example.com:8080".to_string(), /// proxy_secret: "proxy-secret".to_string(), /// }; @@ -531,7 +528,6 @@ mod tests { let publisher = Publisher { domain: "example.com".to_string(), cookie_domain: ".example.com".to_string(), - origin_backend: "publisher_origin".to_string(), origin_url: "https://origin.example.com:8080".to_string(), proxy_secret: "test-secret".to_string(), }; @@ -541,7 +537,6 @@ mod tests { let publisher = Publisher { domain: "example.com".to_string(), cookie_domain: ".example.com".to_string(), - origin_backend: "publisher_origin".to_string(), origin_url: "https://origin.example.com".to_string(), proxy_secret: "test-secret".to_string(), }; @@ -551,7 +546,6 @@ mod tests { let publisher = Publisher { domain: "example.com".to_string(), cookie_domain: ".example.com".to_string(), - origin_backend: "publisher_origin".to_string(), origin_url: "http://localhost:9090".to_string(), proxy_secret: "test-secret".to_string(), }; @@ -561,7 +555,6 @@ mod tests { let publisher = Publisher { domain: "example.com".to_string(), cookie_domain: ".example.com".to_string(), - origin_backend: "publisher_origin".to_string(), origin_url: "localhost:9090".to_string(), proxy_secret: "test-secret".to_string(), }; @@ -571,7 +564,6 @@ mod tests { let publisher = Publisher { domain: "example.com".to_string(), cookie_domain: ".example.com".to_string(), - origin_backend: "publisher_origin".to_string(), origin_url: "http://192.168.1.1:8080".to_string(), proxy_secret: "test-secret".to_string(), }; @@ -581,7 +573,6 @@ mod tests { let publisher = Publisher { domain: "example.com".to_string(), cookie_domain: ".example.com".to_string(), - origin_backend: "publisher_origin".to_string(), origin_url: "http://[::1]:8080".to_string(), proxy_secret: "test-secret".to_string(), }; diff --git a/trusted-server.toml b/trusted-server.toml index 47b4fb0..73455f8 100644 --- a/trusted-server.toml +++ b/trusted-server.toml @@ -5,8 +5,6 @@ sync_url = "https://adapi-srv-eu.smartadserver.com/ac?pgid=2040327&fmtid=137675& [publisher] domain = "test-publisher.com" cookie_domain = ".test-publisher.com" -# DEPRECATED origin backend is now dynamically created -origin_backend = "publisher_origin" origin_url = "https://origin.test-publisher.com" proxy_secret = "change-me-proxy-secret" From 1a128f97e6d5e27c9dfaace7801dcf26f0c365bb Mon Sep 17 00:00:00 2001 From: Christian Date: Tue, 14 Oct 2025 07:08:59 -0500 Subject: [PATCH 4/4] update CHANGELOG.md --- CHANGELOG.md | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 023b25c..b7a81bc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,16 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [1.2.0] - 2025-10-14 + +### Changed +- Publisher origin backend now uses `publisher.origin_url` to dynamically create backends, deprecated `publisher.origin_backend` field +- Prebid backend now uses `prebid.server_url` to dynamically create backends, deprecated `prebid.prebid_backend` field +- Removed static backend definitions from `fastly.toml` for publisher and prebid + +### Added +- Added `.rust-analyzer.json` for improved development environment support with Neovim/rust-analyzer + ## [1.1.0] - 2025-10-05 ### Added @@ -82,7 +92,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Initial implementation of Trusted Server -[Unreleased]:https://github.com/IABTechLab/trusted-server/compare/v1.0.6...HEAD +[Unreleased]:https://github.com/IABTechLab/trusted-server/compare/v1.2.0...HEAD +[1.2.0]:https://github.com/IABTechLab/trusted-server/compare/v1.1.0...v1.2.0 +[1.1.0]:https://github.com/IABTechLab/trusted-server/compare/v1.0.6...v1.1.0 [1.0.6]:https://github.com/IABTechLab/trusted-server/compare/v1.0.5...v1.0.6 [1.0.5]:https://github.com/IABTechLab/trusted-server/compare/v1.0.4...v1.0.5 [1.0.4]:https://github.com/IABTechLab/trusted-server/compare/v1.0.3...v1.0.4