Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 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
1 change: 1 addition & 0 deletions Cargo.lock

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

1 change: 1 addition & 0 deletions crates/common/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,5 @@ tokio = { version = "1.46", features = ["sync", "macros", "io-util", "rt", "time
url = "2.4.1"

[dev-dependencies]
regex = "1.1.1"
temp-env = "0.3.6"
18 changes: 13 additions & 5 deletions crates/common/src/cookies.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ use cookie::{Cookie, CookieJar};
use fastly::http::header;
use fastly::Request;

use crate::settings::Settings;

const COOKIE_MAX_AGE: i32 = 365 * 24 * 60 * 60; // 1 year

// return empty cookie jar for unparsable cookies
Expand Down Expand Up @@ -31,15 +33,17 @@ pub fn handle_request_cookies(req: &Request) -> Option<CookieJar> {
}
}

pub fn create_synthetic_cookie(synthetic_id: &str) -> String {
pub fn create_synthetic_cookie(settings: &Settings, synthetic_id: &str) -> String {
format!(
"synthetic_id={}; Domain=.auburndao.com; Path=/; Secure; SameSite=Lax; Max-Age={}",
synthetic_id, COOKIE_MAX_AGE,
"synthetic_id={}; Domain={}; Path=/; Secure; SameSite=Lax; Max-Age={}",
synthetic_id, settings.publisher.cookie_domain, COOKIE_MAX_AGE,
)
}

#[cfg(test)]
mod tests {
use crate::test_support::tests::create_test_settings;

use super::*;

#[test]
Expand Down Expand Up @@ -113,10 +117,14 @@ mod tests {

#[test]
fn test_create_synthetic_cookie() {
let result = create_synthetic_cookie("12345");
let settings = create_test_settings();
let result = create_synthetic_cookie(&settings, "12345");
assert_eq!(
result,
"synthetic_id=12345; Domain=.auburndao.com; Path=/; Secure; SameSite=Lax; Max-Age=31536000"
format!(
"synthetic_id=12345; Domain={}; Path=/; Secure; SameSite=Lax; Max-Age={}",
settings.publisher.cookie_domain, COOKIE_MAX_AGE,
)
);
}
}
42 changes: 17 additions & 25 deletions crates/common/src/gdpr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,14 +58,15 @@ pub fn get_consent_from_request(req: &Request) -> Option<GdprConsent> {
None
}

pub fn create_consent_cookie(consent: &GdprConsent) -> String {
pub fn create_consent_cookie(settings: &Settings, consent: &GdprConsent) -> String {
format!(
"gdpr_consent={}; Domain=.auburndao.com; Path=/; Secure; SameSite=Lax; Max-Age=31536000",
serde_json::to_string(consent).unwrap_or_default()
"gdpr_consent={}; Domain={}; Path=/; Secure; SameSite=Lax; Max-Age=31536000",
serde_json::to_string(consent).unwrap_or_default(),
settings.publisher.cookie_domain,
)
}

pub fn handle_consent_request(_settings: &Settings, req: Request) -> Result<Response, Error> {
pub fn handle_consent_request(settings: &Settings, req: Request) -> Result<Response, Error> {
match *req.get_method() {
Method::GET => {
// Return current consent status
Expand All @@ -81,7 +82,10 @@ pub fn handle_consent_request(_settings: &Settings, req: Request) -> Result<Resp
.with_header(header::CONTENT_TYPE, "application/json")
.with_body(serde_json::to_string(&consent)?);

response.set_header(header::SET_COOKIE, create_consent_cookie(&consent));
response.set_header(
header::SET_COOKIE,
create_consent_cookie(settings, &consent),
);
Ok(response)
}
_ => {
Expand Down Expand Up @@ -132,23 +136,7 @@ mod tests {
use super::*;
use fastly::{Body, Request};

fn create_test_settings() -> Settings {
Settings {
ad_server: crate::settings::AdServer {
ad_partner_url: "https://test.com".to_string(),
sync_url: "https://sync.test.com".to_string(),
},
prebid: crate::settings::Prebid {
server_url: "https://prebid.test.com".to_string(),
},
synthetic: crate::settings::Synthetic {
counter_store: "test-counter".to_string(),
opid_store: "test-opid".to_string(),
secret_key: "test-secret".to_string(),
template: "{{test}}".to_string(),
},
}
}
use crate::test_support::tests::create_test_settings;

#[test]
fn test_gdpr_consent_default() {
Expand Down Expand Up @@ -196,6 +184,7 @@ mod tests {

#[test]
fn test_create_consent_cookie() {
let settings = create_test_settings();
let consent = GdprConsent {
analytics: true,
advertising: true,
Expand All @@ -204,9 +193,9 @@ mod tests {
version: "1.0".to_string(),
};

let cookie = create_consent_cookie(&consent);
let cookie = create_consent_cookie(&settings, &consent);
assert!(cookie.starts_with("gdpr_consent="));
assert!(cookie.contains("Domain=.auburndao.com"));
assert!(cookie.contains(format!("Domain={}", settings.publisher.cookie_domain).as_str()));
assert!(cookie.contains("Path=/"));
assert!(cookie.contains("Secure"));
assert!(cookie.contains("SameSite=Lax"));
Expand Down Expand Up @@ -297,7 +286,10 @@ mod tests {
let set_cookie = response.get_header_str(header::SET_COOKIE);
assert!(set_cookie.is_some());
assert!(set_cookie.unwrap().contains("gdpr_consent="));
assert!(set_cookie.unwrap().contains("Domain=.auburndao.com"));

assert!(set_cookie
.unwrap()
.contains(format!("Domain={}", settings.publisher.cookie_domain).as_str()));

// Check response body
let body = response.into_body_str();
Expand Down
1 change: 1 addition & 0 deletions crates/common/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@ pub mod privacy;
pub mod settings;
pub mod synthetic;
pub mod templates;
pub mod test_support;
pub mod why;
42 changes: 15 additions & 27 deletions crates/common/src/prebid.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ impl PrebidRequest {
.and_then(|o| url::Url::parse(o).ok())
.and_then(|u| u.host_str().map(|h| h.to_string()))
})
.unwrap_or_else(|| "auburndao.com".to_string());
.unwrap_or_else(|| settings.publisher.domain.clone());

log::info!("Detected domain: {}", domain);

Expand Down Expand Up @@ -192,23 +192,7 @@ mod tests {
use super::*;
use fastly::Request;

fn create_test_settings() -> Settings {
Settings {
ad_server: crate::settings::AdServer {
ad_partner_url: "https://test.com".to_string(),
sync_url: "https://sync.test.com".to_string(),
},
prebid: crate::settings::Prebid {
server_url: "https://prebid.test.com/openrtb2/auction".to_string(),
},
synthetic: crate::settings::Synthetic {
counter_store: "test-counter".to_string(),
opid_store: "test-opid".to_string(),
secret_key: "test-secret-key".to_string(),
template: "{{client_ip}}:{{user_agent}}:{{first_party_id}}:{{auth_user_id}}:{{publisher_domain}}:{{accept_language}}".to_string(),
},
}
}
use crate::test_support::tests::create_test_settings;

#[test]
fn test_prebid_request_new_with_full_headers() {
Expand Down Expand Up @@ -258,31 +242,34 @@ mod tests {
#[test]
fn test_prebid_request_domain_fallback() {
let settings = create_test_settings();
let req = Request::get("https://example.com/test");
let url = format!("https://{}", settings.publisher.domain);
let req = Request::get(url.clone());
// No referer or origin headers

let prebid_req = PrebidRequest::new(&settings, &req).unwrap();

assert_eq!(prebid_req.domain, "auburndao.com");
assert_eq!(prebid_req.origin, "https://auburndao.com");
assert_eq!(prebid_req.domain, settings.publisher.domain);
assert_eq!(prebid_req.origin, url);
}

#[test]
fn test_prebid_request_invalid_url_in_referer() {
let settings = create_test_settings();
let mut req = Request::get("https://example.com/test");
let url = format!("https://{}/test", settings.publisher.domain);
let mut req = Request::get(url);
req.set_header(header::REFERER, "not-a-valid-url");

let prebid_req = PrebidRequest::new(&settings, &req).unwrap();

// Should fallback to default domain
assert_eq!(prebid_req.domain, "auburndao.com");
assert_eq!(prebid_req.domain, settings.publisher.domain);
}

#[test]
fn test_prebid_request_x_forwarded_for_parsing() {
let settings = create_test_settings();
let mut req = Request::get("https://example.com/test");
let url = format!("https://{}/test", settings.publisher.domain);
let mut req = Request::get(url);
req.set_header(HEADER_X_FORWARDED_FOR, "192.168.1.1, 10.0.0.1, 172.16.0.1");

let prebid_req = PrebidRequest::new(&settings, &req).unwrap();
Expand Down Expand Up @@ -330,18 +317,19 @@ mod tests {
#[test]
fn test_prebid_request_edge_cases() {
let settings = create_test_settings();
let url = format!("https://{}/test", settings.publisher.domain);

// Test with empty X-Forwarded-For
let mut req = Request::get("https://example.com/test");
let mut req = Request::get(url.clone());
req.set_header(HEADER_X_FORWARDED_FOR, "");
let prebid_req = PrebidRequest::new(&settings, &req).unwrap();
assert!(!prebid_req.client_ip.is_empty() || prebid_req.client_ip.is_empty());

// Test with malformed origin
let mut req2 = Request::get("https://example.com/test");
let mut req2 = Request::get(url.clone());
req2.set_header(header::ORIGIN, "://invalid");
let prebid_req2 = PrebidRequest::new(&settings, &req2).unwrap();
assert_eq!(prebid_req2.domain, "auburndao.com");
assert_eq!(prebid_req2.domain, settings.publisher.domain);
}

// Note: Testing send_bid_request would require mocking the Fastly backend,
Expand Down
Loading