Skip to content
Open
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
4 changes: 3 additions & 1 deletion crates/trusted-server-adapter-axum/src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use edgezero_core::router::RouterService;
use error_stack::Report;
use trusted_server_core::auction::endpoints::handle_auction;
use trusted_server_core::auction::{AuctionOrchestrator, build_orchestrator};
use trusted_server_core::cache_policy::EdgeCacheHeader;
use trusted_server_core::ec::EcContext;
use trusted_server_core::error::{IntoHttpResponse as _, TrustedServerError};
use trusted_server_core::integrations::{IntegrationRegistry, ProxyDispatchInput};
Expand Down Expand Up @@ -176,7 +177,7 @@ async fn dispatch_fallback(
let method = req.method().clone();

if method == Method::GET && path.starts_with("/static/tsjs=") {
return handle_tsjs_dynamic(&req, &state.registry);
return handle_tsjs_dynamic(&req, &state.registry, EdgeCacheHeader::SMaxageFallback);
}

if state.registry.has_route(&method, &path) {
Expand Down Expand Up @@ -215,6 +216,7 @@ async fn dispatch_fallback(
&mut ec_context,
auction,
req,
EdgeCacheHeader::SMaxageFallback,
)
.await?;
// Async finalize so the dispatched auction is collected and its bids are
Expand Down
36 changes: 36 additions & 0 deletions crates/trusted-server-adapter-axum/tests/routes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,42 @@ async fn tsjs_route_prefix_is_handled_not_5xx() {
);
}

#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn tsjs_route_matching_hash_uses_s_maxage_fallback() {
let mut svc = make_service();
let src = trusted_server_core::tsjs::tsjs_script_src(&["creative"]);
let req = Request::builder()
.method("GET")
.uri(src)
.body(AxumBody::empty())
.expect("should build request");

let resp = svc
.ready()
.await
.expect("should be ready")
.call(req)
.await
.expect("should respond");

assert_eq!(
resp.status().as_u16(),
200,
"matching TSJS hash should serve OK"
);
assert_eq!(
resp.headers()
.get("cache-control")
.and_then(|value| value.to_str().ok()),
Some("public, max-age=31536000, s-maxage=31536000, immutable"),
"Axum adapter should render the portable s-maxage fallback"
);
assert!(
resp.headers().get("surrogate-control").is_none(),
"s-maxage fallback must not emit Fastly Surrogate-Control"
);
}

// ---------------------------------------------------------------------------
// Middleware tests
// ---------------------------------------------------------------------------
Expand Down
8 changes: 7 additions & 1 deletion crates/trusted-server-adapter-cloudflare/src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use edgezero_core::router::RouterService;
use error_stack::Report;
use trusted_server_core::auction::endpoints::handle_auction;
use trusted_server_core::auction::{AuctionOrchestrator, build_orchestrator};
use trusted_server_core::cache_policy::EdgeCacheHeader;
#[cfg(target_arch = "wasm32")]
use trusted_server_core::config_payload::settings_from_config_blob;
use trusted_server_core::ec::EcContext;
Expand Down Expand Up @@ -367,7 +368,11 @@ fn build_router(state: &Arc<AppState>) -> RouterService {
let allow_tsjs = method == Method::GET;

let result = if allow_tsjs && path.starts_with("/static/tsjs=") {
handle_tsjs_dynamic(&req, &state.registry)
handle_tsjs_dynamic(
&req,
&state.registry,
EdgeCacheHeader::CloudflareCdnCacheControl,
)
} else if state.registry.has_route(&method, &path) {
let mut ec_context = EcContext::default();
state
Expand Down Expand Up @@ -401,6 +406,7 @@ fn build_router(state: &Arc<AppState>) -> RouterService {
&mut ec_context,
auction,
req,
EdgeCacheHeader::CloudflareCdnCacheControl,
)
.await
{
Expand Down
37 changes: 37 additions & 0 deletions crates/trusted-server-adapter-cloudflare/tests/routes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,43 @@ async fn tsjs_route_is_routed_not_5xx() {
assert!(status < 500, "tsjs route must not 5xx: got {status}");
}

#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn tsjs_route_emits_cloudflare_cache_header_for_matching_hash() {
let router = test_router();
let src = trusted_server_core::tsjs::tsjs_script_src(&["creative"]);
let req = request_builder()
.method("GET")
.uri(src)
.body(edgezero_core::body::Body::empty())
.expect("should build request");

let resp = route(router, req).await;

assert_eq!(
resp.status().as_u16(),
200,
"matching TSJS hash should serve OK"
);
assert_eq!(
resp.headers()
.get("cache-control")
.and_then(|value| value.to_str().ok()),
Some("public, max-age=31536000, immutable"),
"browser cache policy should be immutable for matching TSJS hash"
);
assert_eq!(
resp.headers()
.get("cloudflare-cdn-cache-control")
.and_then(|value| value.to_str().ok()),
Some("max-age=31536000"),
"Cloudflare adapter should emit the Cloudflare-specific edge header"
);
assert!(
resp.headers().get("surrogate-control").is_none(),
"Cloudflare adapter must not emit Fastly Surrogate-Control"
);
}

/// Verify that every expected explicit route is registered in the route table.
///
/// Uses [`RouterService::routes()`] for introspection rather than checking
Expand Down
4 changes: 3 additions & 1 deletion crates/trusted-server-adapter-fastly/src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ use error_stack::Report;
use trusted_server_core::auction::endpoints::handle_auction;
use trusted_server_core::auction::AuctionTelemetrySink;
use trusted_server_core::auction::{build_orchestrator, AuctionOrchestrator};
use trusted_server_core::cache_policy::EdgeCacheHeader;
use trusted_server_core::constants::{COOKIE_SHAREDID, COOKIE_TS_EIDS};
use trusted_server_core::ec::batch_sync::handle_batch_sync;
use trusted_server_core::ec::consent::ec_consent_withdrawn;
Expand Down Expand Up @@ -719,7 +720,7 @@ async fn dispatch_fallback(
};

let result = if uses_dynamic_tsjs_fallback(&method, &path) {
handle_tsjs_dynamic(&req, &state.registry)
handle_tsjs_dynamic(&req, &state.registry, EdgeCacheHeader::SurrogateControl)
} else if state.registry.has_route(&method, &path) {
// Integration-proxy responses are not bounded by publisher.max_buffered_body_bytes.
// Only the handle_publisher_request branch below routes through
Expand Down Expand Up @@ -794,6 +795,7 @@ async fn dispatch_fallback(
&mut ec.ec_context,
auction,
req,
EdgeCacheHeader::SurrogateControl,
)
.await
{
Expand Down
3 changes: 2 additions & 1 deletion crates/trusted-server-adapter-fastly/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use error_stack::Report;
use fastly::http::Method as FastlyMethod;
use fastly::{Request as FastlyRequest, Response as FastlyResponse};

use trusted_server_core::cache_policy::EdgeCacheHeader;
use trusted_server_core::ec::device::DeviceSignals;
use trusted_server_core::ec::finalize::ec_finalize_response;
use trusted_server_core::ec::kv::KvIdentityGraph;
Expand Down Expand Up @@ -202,7 +203,7 @@ fn edgezero_main(mut req: FastlyRequest) {
}

if let Some(policy) = asset_cache_policy {
policy.apply_after_route_finalization(&mut response);
policy.apply_after_route_finalization(&mut response, EdgeCacheHeader::SurrogateControl);
}

if let Some(ec_state) = ec_state {
Expand Down
4 changes: 3 additions & 1 deletion crates/trusted-server-adapter-spin/src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use edgezero_core::router::RouterService;
use error_stack::Report;
use trusted_server_core::auction::endpoints::handle_auction;
use trusted_server_core::auction::{AuctionOrchestrator, build_orchestrator};
use trusted_server_core::cache_policy::EdgeCacheHeader;
use trusted_server_core::ec::EcContext;
use trusted_server_core::error::{IntoHttpResponse as _, TrustedServerError};
use trusted_server_core::http_util::sanitize_forwarded_headers;
Expand Down Expand Up @@ -637,7 +638,7 @@ fn build_router(state: &Arc<AppState>) -> RouterService {
// Dynamic tsjs serving is GET-only; other methods fall through to the
// integration/publisher fallback.
let result = if method == Method::GET && path.starts_with("/static/tsjs=") {
handle_tsjs_dynamic(&req, &state.registry)
handle_tsjs_dynamic(&req, &state.registry, EdgeCacheHeader::SMaxageFallback)
} else if state.registry.has_route(&method, &path) {
let mut ec_context = EcContext::default();
state
Expand Down Expand Up @@ -671,6 +672,7 @@ fn build_router(state: &Arc<AppState>) -> RouterService {
&mut ec_context,
auction,
req,
EdgeCacheHeader::SMaxageFallback,
)
.await
{
Expand Down
30 changes: 30 additions & 0 deletions crates/trusted-server-adapter-spin/tests/routes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,36 @@ async fn tsjs_route_is_routed_not_5xx() {
assert!(status < 500, "tsjs route must not 5xx: got {status}");
}

#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn tsjs_route_matching_hash_uses_s_maxage_fallback() {
let router = test_router();
let src = trusted_server_core::tsjs::tsjs_script_src(&["creative"]);
let req = request_builder()
.method("GET")
.uri(src)
.body(edgezero_core::body::Body::empty())
.expect("should build request");

let resp = route(router, req).await;

assert_eq!(
resp.status().as_u16(),
200,
"matching TSJS hash should serve OK"
);
assert_eq!(
resp.headers()
.get("cache-control")
.and_then(|value| value.to_str().ok()),
Some("public, max-age=31536000, s-maxage=31536000, immutable"),
"Spin adapter should render the portable s-maxage fallback"
);
assert!(
resp.headers().get("surrogate-control").is_none(),
"s-maxage fallback must not emit Fastly Surrogate-Control"
);
}

#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn verify_signature_is_routed() {
let router = test_router();
Expand Down
Loading
Loading