Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
01305cf
Add one module context and the adapter that injects what a module names
jwrosewell Oct 8, 2026
8921de1
The device module is handed the module context
jwrosewell Oct 8, 2026
80a3527
The Edge Cookie module is handed the module context
jwrosewell Oct 8, 2026
4350d15
The permission signal modules are handed the module context
jwrosewell Oct 8, 2026
8d18b40
Module routes are handed the module context
jwrosewell Oct 8, 2026
d48858f
The module context carries only what a module is handed
jwrosewell Oct 8, 2026
e8c7ef5
The integration guide says what a module is handed
jwrosewell Oct 8, 2026
359e30a
A value absent where a route runs answers 500, and each rule is said …
Jamesr51d Oct 12, 2026
3f25457
Merge split/7-integration-seam-impl into split/8-module-context
Jamesr51d Oct 13, 2026
bc28b3e
Merge split/7-integration-seam-impl into split/8-module-context
Jamesr51d Oct 13, 2026
dfe63ab
Merge split/7-integration-seam-impl into split/8-module-context
jwrosewell Oct 15, 2026
facbcca
Merge split/7-integration-seam-impl into split/8-module-context
jwrosewell Oct 16, 2026
06032f5
Merge split/7-integration-seam-impl into split/8-module-context
jwrosewell Oct 16, 2026
b607900
Merge split/7-integration-seam-impl into split/8-module-context
jwrosewell Oct 16, 2026
af65922
Merge split/7-integration-seam-impl into split/8-module-context
jwrosewell Oct 16, 2026
a3a3263
Merge split/7-integration-seam-impl into split/8-module-context
jwrosewell Oct 16, 2026
108b8a0
Merge split/7-integration-seam-impl into split/8-module-context
jwrosewell Oct 18, 2026
c2b36af
Merge split/7-integration-seam-impl into split/8-module-context
jwrosewell Oct 18, 2026
d5ba945
Merge split/7-integration-seam-impl into split/8-module-context
jwrosewell Oct 18, 2026
b9a7b37
Merge split/7-integration-seam-impl into split/8-module-context
jwrosewell Oct 18, 2026
f151cfb
Merge split/7-integration-seam-impl into split/8-module-context
jwrosewell Oct 19, 2026
e72fc9a
Merge split/7-integration-seam-impl into split/8-module-context
jwrosewell Oct 19, 2026
4a7618b
Merge split/7-integration-seam-impl into split/8-module-context
jwrosewell Oct 19, 2026
6a0561c
Merge split/7-integration-seam-impl into split/8-module-context
jwrosewell Oct 19, 2026
55ba8ef
Merge split/7-integration-seam-impl into split/8-module-context
jwrosewell Oct 28, 2026
9b3fc72
Merge split/7-integration-seam-impl into split/8-module-context
jwrosewell Oct 28, 2026
4f3225f
Merge split/7-integration-seam-impl into split/8-module-context
jwrosewell Oct 28, 2026
f241b3f
Merge split/7-integration-seam-impl into split/8-module-context
jwrosewell Oct 28, 2026
9eaa130
Merge split/7-integration-seam-impl into split/8-module-context
jwrosewell Oct 28, 2026
2d2b238
Merge split/7-integration-seam-impl into split/8-module-context
jwrosewell Oct 28, 2026
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
42 changes: 26 additions & 16 deletions crates/ad-tag/google/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -440,25 +440,12 @@ pub fn register(
))
}

#[async_trait(?Send)]
impl IntegrationProxy for GptIntegration {
fn integration_name(&self) -> &'static str {
GPT_INTEGRATION_ID
}

fn routes(&self) -> Vec<IntegrationEndpoint> {
vec![
self.get("/script"),
self.get("/pagead/*"),
self.get("/tag/*"),
]
}

async fn handle(
impl GptIntegration {
async fn route(
&self,
req: http::Request<EdgeBody>,
settings: &Settings,
services: &RuntimeServices,
req: http::Request<EdgeBody>,
) -> Result<http::Response<EdgeBody>, Report<TrustedServerError>> {
let path = req.uri().path().to_string();

Expand All @@ -477,6 +464,29 @@ impl IntegrationProxy for GptIntegration {
}
}

#[async_trait(?Send)]
impl IntegrationProxy for GptIntegration {
fn integration_name(&self) -> &'static str {
GPT_INTEGRATION_ID
}

fn routes(&self) -> Vec<IntegrationEndpoint> {
vec![
self.get("/script"),
self.get("/pagead/*"),
self.get("/tag/*"),
]
}

async fn handle(
&self,
call: trusted_server_core::module_context::ModuleCall<'_>,
req: http::Request<EdgeBody>,
) -> Result<http::Response<EdgeBody>, Report<TrustedServerError>> {
call.inject_with(self, req, Self::route)?.await
}
}

impl IntegrationAttributeRewriter for GptIntegration {
fn integration_id(&self) -> &'static str {
GPT_INTEGRATION_ID
Expand Down
26 changes: 15 additions & 11 deletions crates/auction/aps/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,9 @@ use trusted_server_core::openrtb::{
Banner, Device, Format, Geo, Imp, OpenRtbRequest, Publisher, Regs, RegsExt, Site, User,
UserExt, to_openrtb_i32,
};
use trusted_server_core::platform::PlatformResponse;
#[cfg(test)]
use trusted_server_core::platform::PlatformHttpRequest;
use trusted_server_core::platform::{PlatformResponse, RuntimeServices};
use trusted_server_core::platform::{PlatformHttpRequest, RuntimeServices};
use trusted_server_core::settings::Settings;

pub(crate) const APS_INTEGRATION_ID: &str = "aps";
Expand Down Expand Up @@ -2048,10 +2048,11 @@ impl IntegrationProxy for ApsRendererIntegration {
.collect()
}

// The renderer page is the same for every request, so the route takes
// nothing from its module call.
async fn handle(
&self,
_settings: &Settings,
_services: &RuntimeServices,
_call: trusted_server_core::module_context::ModuleCall<'_>,
request: http::Request<EdgeBody>,
) -> Result<http::Response<EdgeBody>, Report<TrustedServerError>> {
if request.method() != Method::GET || request.uri().path() != APS_RENDERER_ROUTE {
Expand Down Expand Up @@ -3206,16 +3207,16 @@ mod tests {
assert_eq!(routes[0].method, Method::GET);
assert_eq!(routes[0].path, APS_RENDERER_ROUTE);

let settings = create_test_settings();
let services = noop_services();
let request = http::Request::builder()
.method(Method::GET)
.uri(APS_RENDERER_ROUTE)
.body(EdgeBody::empty())
.expect("should build renderer request");
let response =
futures::executor::block_on(integration.handle(&settings, &services, request))
.expect("should serve renderer");
let response = futures::executor::block_on(integration.handle(
trusted_server_core::module_context::ModuleCall::empty(),
request,
))
.expect("should serve renderer");
assert_eq!(response.status(), StatusCode::OK);
assert_eq!(
response.headers()[header::CONTENT_TYPE],
Expand All @@ -3233,8 +3234,11 @@ mod tests {
.uri(APS_RENDERER_ROUTE)
.body(EdgeBody::empty())
.expect("should build method rejection request");
let response = futures::executor::block_on(integration.handle(&settings, &services, post))
.expect("should reject unsupported method");
let response = futures::executor::block_on(integration.handle(
trusted_server_core::module_context::ModuleCall::empty(),
post,
))
.expect("should reject unsupported method");
assert_eq!(response.status(), StatusCode::NOT_FOUND);
}

Expand Down
48 changes: 29 additions & 19 deletions crates/auction/prebid/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1126,6 +1126,33 @@ pub fn register(
))
}

impl PrebidIntegration {
async fn route(
&self,
req: http::Request<EdgeBody>,
settings: &Settings,
services: &RuntimeServices,
) -> Result<http::Response<EdgeBody>, Report<TrustedServerError>> {
let path = req.uri().path().to_string();
let method = req.method().clone();

match method {
Method::GET if self.is_managed_external() && path == PREBID_BUNDLE_ROUTE => {
self.handle_external_bundle(settings, services, req).await
}
// Serve empty JS for matching script patterns
Method::GET if self.matches_script_pattern(&path) => self.handle_script_handler(),
_ => http::Response::builder()
.status(StatusCode::NOT_FOUND)
.body(EdgeBody::from("Not Found"))
.change_context(TrustedServerError::Integration {
integration: PREBID_INTEGRATION_ID.to_string(),
message: "Failed to build Prebid not found response".to_string(),
}),
}
}
}

#[async_trait(?Send)]
impl IntegrationProxy for PrebidIntegration {
fn integration_name(&self) -> &'static str {
Expand All @@ -1152,27 +1179,10 @@ impl IntegrationProxy for PrebidIntegration {

async fn handle(
&self,
settings: &Settings,
services: &RuntimeServices,
call: trusted_server_core::module_context::ModuleCall<'_>,
req: http::Request<EdgeBody>,
) -> Result<http::Response<EdgeBody>, Report<TrustedServerError>> {
let path = req.uri().path().to_string();
let method = req.method().clone();

match method {
Method::GET if self.is_managed_external() && path == PREBID_BUNDLE_ROUTE => {
self.handle_external_bundle(settings, services, req).await
}
// Serve empty JS for matching script patterns
Method::GET if self.matches_script_pattern(&path) => self.handle_script_handler(),
_ => http::Response::builder()
.status(StatusCode::NOT_FOUND)
.body(EdgeBody::from("Not Found"))
.change_context(TrustedServerError::Integration {
integration: PREBID_INTEGRATION_ID.to_string(),
message: "Failed to build Prebid not found response".to_string(),
}),
}
call.inject_with(self, req, Self::route)?.await
}
}

Expand Down
74 changes: 42 additions & 32 deletions crates/audience/permutive/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -357,38 +357,12 @@ pub fn register(
))
}

#[async_trait(?Send)]
impl IntegrationProxy for PermutiveIntegration {
fn integration_name(&self) -> &'static str {
PERMUTIVE_INTEGRATION_ID
}

fn routes(&self) -> Vec<IntegrationEndpoint> {
vec![
// API proxy endpoints
self.get("/api/*"),
self.post("/api/*"),
// Secure Signals endpoints
self.get("/secure-signal/*"),
self.post("/secure-signal/*"),
// Events endpoints
self.get("/events/*"),
self.post("/events/*"),
// Sync endpoints
self.get("/sync/*"),
self.post("/sync/*"),
// CDN endpoint
self.get("/cdn/*"),
// SDK serving
self.get("/sdk"),
]
}

async fn handle(
impl PermutiveIntegration {
async fn route(
&self,
req: http::Request<EdgeBody>,
settings: &Settings,
services: &RuntimeServices,
req: http::Request<EdgeBody>,
) -> Result<http::Response<EdgeBody>, Report<TrustedServerError>> {
let path = req.uri().path().to_string();

Expand Down Expand Up @@ -448,6 +422,42 @@ impl IntegrationProxy for PermutiveIntegration {
}
}

#[async_trait(?Send)]
impl IntegrationProxy for PermutiveIntegration {
fn integration_name(&self) -> &'static str {
PERMUTIVE_INTEGRATION_ID
}

fn routes(&self) -> Vec<IntegrationEndpoint> {
vec![
// API proxy endpoints
self.get("/api/*"),
self.post("/api/*"),
// Secure Signals endpoints
self.get("/secure-signal/*"),
self.post("/secure-signal/*"),
// Events endpoints
self.get("/events/*"),
self.post("/events/*"),
// Sync endpoints
self.get("/sync/*"),
self.post("/sync/*"),
// CDN endpoint
self.get("/cdn/*"),
// SDK serving
self.get("/sdk"),
]
}

async fn handle(
&self,
call: trusted_server_core::module_context::ModuleCall<'_>,
req: http::Request<EdgeBody>,
) -> Result<http::Response<EdgeBody>, Report<TrustedServerError>> {
call.inject_with(self, req, Self::route)?.await
}
}

impl IntegrationAttributeRewriter for PermutiveIntegration {
fn integration_id(&self) -> &'static str {
PERMUTIVE_INTEGRATION_ID
Expand Down Expand Up @@ -678,7 +688,7 @@ mod tests {
.body(EdgeBody::empty())
.expect("should build request");

let response = futures::executor::block_on(integration.handle(&settings, &services, req))
let response = futures::executor::block_on(integration.route(req, &settings, &services))
.expect("should proxy request");

assert_eq!(
Expand Down Expand Up @@ -720,7 +730,7 @@ mod tests {
.body(EdgeBody::empty())
.expect("should build request");

let response = futures::executor::block_on(integration.handle(&settings, &services, req))
let response = futures::executor::block_on(integration.route(req, &settings, &services))
.expect("should proxy request");
assert_eq!(
response.status(),
Expand Down Expand Up @@ -793,7 +803,7 @@ mod tests {
.header("x-permutive-trace", "kept")
.body(EdgeBody::empty())
.expect("should build request");
futures::executor::block_on(integration.handle(&settings, &services, req))
futures::executor::block_on(integration.route(req, &settings, &services))
.expect("should proxy request");
}

Expand Down
40 changes: 24 additions & 16 deletions crates/bot-protection/datadome/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -874,6 +874,27 @@ impl DataDomeIntegration {
}
}

impl DataDomeIntegration {
async fn route(
&self,
req: http::Request<EdgeBody>,
services: &RuntimeServices,
) -> Result<http::Response<EdgeBody>, Report<TrustedServerError>> {
let path = req.uri().path().to_string();

if path == "/integrations/datadome/tags.js" {
self.handle_tags_js(services, req).await
} else if path.starts_with("/integrations/datadome/js/") {
self.handle_js_api(services, req).await
} else {
Err(Report::new(Self::error(format!(
"Unknown DataDome route: {}",
path
))))
}
}
}

#[async_trait(?Send)]
impl IntegrationProxy for DataDomeIntegration {
fn integration_name(&self) -> &'static str {
Expand All @@ -895,22 +916,10 @@ impl IntegrationProxy for DataDomeIntegration {

async fn handle(
&self,
_settings: &Settings,
services: &RuntimeServices,
call: trusted_server_core::module_context::ModuleCall<'_>,
req: http::Request<EdgeBody>,
) -> Result<http::Response<EdgeBody>, Report<TrustedServerError>> {
let path = req.uri().path().to_string();

if path == "/integrations/datadome/tags.js" {
self.handle_tags_js(services, req).await
} else if path.starts_with("/integrations/datadome/js/") {
self.handle_js_api(services, req).await
} else {
Err(Report::new(Self::error(format!(
"Unknown DataDome route: {}",
path
))))
}
call.inject_with(self, req, Self::route)?.await
}
}

Expand Down Expand Up @@ -1718,15 +1727,14 @@ mod tests {
let services = build_services_with_http_client(
Arc::clone(&stub) as Arc<dyn trusted_server_core::platform::PlatformHttpClient>
);
let settings = create_test_settings();
let integration = DataDomeIntegration::new(test_config());
let req = http::Request::builder()
.method(http::Method::GET)
.uri("https://publisher.example/integrations/datadome/js/check")
.body(EdgeBody::empty())
.expect("should build request");

let response = futures::executor::block_on(integration.handle(&settings, &services, req))
let response = futures::executor::block_on(integration.route(req, &services))
.expect("should proxy request");

assert_eq!(
Expand Down
Loading
Loading