Skip to content

Commit a5f8bc8

Browse files
authored
Use constants for headers
1 parent 3b18df4 commit a5f8bc8

File tree

8 files changed

+99
-71
lines changed

8 files changed

+99
-71
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
3434
### Changed
3535
- Upgrade to rust 1.87.0
3636
- Upgrade to fastly-cli 11.3.0
37+
- Changed to use constants for headers
3738

3839
## [1.0.6] - 2025-05-29
3940

Cargo.lock

Lines changed: 3 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/common/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ futures = "0.3"
1717
handlebars = "6.3.2"
1818
hex = "0.4.3"
1919
hmac = "0.12.1"
20+
http = "1.3.1"
2021
log = "0.4.20"
2122
log-fastly = "0.10.0"
2223
serde = { version = "1.0", features = ["derive"] }

crates/common/src/constants.rs

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,21 @@
1-
pub const SYNTHETIC_HEADER_FRESH: &str = "X-Synthetic-Fresh";
2-
pub const SYNTHETIC_HEADER_TRUSTED_SERVER: &str = "X-Synthetic-Trusted-Server";
3-
pub const SYNTHETIC_HEADER_PUB_USER_ID: &str = "X-Pub-User-ID";
1+
use http::header::HeaderName;
2+
3+
pub const HEADER_SYNTHETIC_FRESH: HeaderName = HeaderName::from_static("x-synthetic-fresh");
4+
pub const HEADER_SYNTHETIC_PUB_USER_ID: HeaderName = HeaderName::from_static("x-pub-user-id");
5+
pub const HEADER_X_PUB_USER_ID: HeaderName = HeaderName::from_static("x-pub-user-id");
6+
pub const HEADER_SYNTHETIC_TRUSTED_SERVER: HeaderName =
7+
HeaderName::from_static("x-synthetic-trusted-server");
8+
pub const HEADER_X_CONSENT_ADVERTISING: HeaderName =
9+
HeaderName::from_static("x-consent-advertising");
10+
pub const HEADER_X_FORWARDED_FOR: HeaderName = HeaderName::from_static("x-forwarded-for");
11+
pub const HEADER_X_GEO_CITY: HeaderName = HeaderName::from_static("x-geo-city");
12+
pub const HEADER_X_GEO_CONTINENT: HeaderName = HeaderName::from_static("x-geo-continent");
13+
pub const HEADER_X_GEO_COORDINATES: HeaderName = HeaderName::from_static("x-geo-coordinates");
14+
pub const HEADER_X_GEO_COUNTRY: HeaderName = HeaderName::from_static("x-geo-country");
15+
pub const HEADER_X_GEO_INFO_AVAILABLE: HeaderName = HeaderName::from_static("x-geo-info-available");
16+
pub const HEADER_X_GEO_METRO_CODE: HeaderName = HeaderName::from_static("x-geo-metro-code");
17+
pub const HEADER_X_GEO_REGION: HeaderName = HeaderName::from_static("x-geo-region");
18+
pub const HEADER_X_SUBJECT_ID: HeaderName = HeaderName::from_static("x-subject-id");
19+
pub const HEADER_X_REQUEST_ID: HeaderName = HeaderName::from_static("x-request-id");
20+
pub const HEADER_X_COMPRESS_HINT: HeaderName = HeaderName::from_static("x-compress-hint");
21+
pub const HEADER_X_DEBUG_FASTLY_POP: HeaderName = HeaderName::from_static("x-debug-fastly-pop");

crates/common/src/gdpr.rs

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
1-
use crate::cookies;
2-
use crate::settings::Settings;
31
use fastly::http::{header, Method, StatusCode};
42
use fastly::{Error, Request, Response};
53
use serde::{Deserialize, Serialize};
64
use std::collections::HashMap;
75

6+
use crate::constants::HEADER_X_SUBJECT_ID;
7+
use crate::cookies;
8+
use crate::settings::Settings;
9+
810
#[derive(Debug, Serialize, Deserialize, Clone)]
911
pub struct GdprConsent {
1012
pub analytics: bool,
@@ -93,7 +95,7 @@ pub fn handle_data_subject_request(_settings: &Settings, req: Request) -> Result
9395
match *req.get_method() {
9496
Method::GET => {
9597
// Handle data access request
96-
if let Some(synthetic_id) = req.get_header("X-Subject-ID") {
98+
if let Some(synthetic_id) = req.get_header(HEADER_X_SUBJECT_ID) {
9799
// Create a HashMap to store all user-related data
98100
let mut data: HashMap<String, UserData> = HashMap::new();
99101

@@ -110,7 +112,7 @@ pub fn handle_data_subject_request(_settings: &Settings, req: Request) -> Result
110112
}
111113
Method::DELETE => {
112114
// Handle right to erasure (right to be forgotten)
113-
if let Some(_synthetic_id) = req.get_header("X-Subject-ID") {
115+
if let Some(_synthetic_id) = req.get_header(HEADER_X_SUBJECT_ID) {
114116
// TODO: Implement data deletion from KV store
115117
Ok(Response::from_status(StatusCode::OK)
116118
.with_body("Data deletion request processed"))
@@ -319,7 +321,7 @@ mod tests {
319321
fn test_handle_data_subject_request_get_with_id() {
320322
let settings = create_test_settings();
321323
let mut req = Request::get("https://example.com/gdpr/data");
322-
req.set_header("X-Subject-ID", "test-subject-123");
324+
req.set_header(HEADER_X_SUBJECT_ID, "test-subject-123");
323325

324326
let response = handle_data_subject_request(&settings, req).unwrap();
325327
assert_eq!(response.get_status(), StatusCode::OK);
@@ -348,7 +350,7 @@ mod tests {
348350
fn test_handle_data_subject_request_delete_with_id() {
349351
let settings = create_test_settings();
350352
let mut req = Request::delete("https://example.com/gdpr/data");
351-
req.set_header("X-Subject-ID", "test-subject-123");
353+
req.set_header(HEADER_X_SUBJECT_ID, "test-subject-123");
352354

353355
let response = handle_data_subject_request(&settings, req).unwrap();
354356
assert_eq!(response.get_status(), StatusCode::OK);

crates/common/src/prebid.rs

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@ use fastly::http::{header, Method};
22
use fastly::{Error, Request, Response};
33
use serde_json::json;
44

5-
use crate::constants::{SYNTHETIC_HEADER_FRESH, SYNTHETIC_HEADER_TRUSTED_SERVER};
5+
use crate::constants::{
6+
HEADER_SYNTHETIC_FRESH, HEADER_SYNTHETIC_TRUSTED_SERVER, HEADER_X_FORWARDED_FOR,
7+
};
68
use crate::settings::Settings;
79
use crate::synthetic::generate_synthetic_id;
810

@@ -31,7 +33,7 @@ impl PrebidRequest {
3133
pub fn new(settings: &Settings, req: &Request) -> Result<Self, Error> {
3234
// Get the Trusted Server ID from header (which we just set in handle_prebid_test)
3335
let synthetic_id = req
34-
.get_header(SYNTHETIC_HEADER_TRUSTED_SERVER)
36+
.get_header(HEADER_SYNTHETIC_TRUSTED_SERVER)
3537
.and_then(|h| h.to_str().ok())
3638
.map(|s| s.to_string())
3739
.unwrap_or_else(|| generate_synthetic_id(settings, req));
@@ -41,7 +43,7 @@ impl PrebidRequest {
4143
.get_client_ip_addr()
4244
.map(|ip| ip.to_string())
4345
.unwrap_or_else(|| {
44-
req.get_header("X-Forwarded-For")
46+
req.get_header(HEADER_X_FORWARDED_FOR)
4547
.and_then(|h| h.to_str().ok())
4648
.unwrap_or("")
4749
.split(',') // X-Forwarded-For can be a comma-separated list
@@ -98,7 +100,7 @@ impl PrebidRequest {
98100

99101
// Get and store the POTSI ID value from the incoming request
100102
let id: String = incoming_req
101-
.get_header(SYNTHETIC_HEADER_TRUSTED_SERVER)
103+
.get_header(HEADER_SYNTHETIC_TRUSTED_SERVER)
102104
.and_then(|h| h.to_str().ok())
103105
.map(|s| s.to_string())
104106
.unwrap_or_else(|| self.synthetic_id.clone());
@@ -167,10 +169,10 @@ impl PrebidRequest {
167169
});
168170

169171
req.set_header(header::CONTENT_TYPE, "application/json");
170-
req.set_header("X-Forwarded-For", &self.client_ip);
172+
req.set_header(HEADER_X_FORWARDED_FOR, &self.client_ip);
171173
req.set_header(header::ORIGIN, &self.origin);
172-
req.set_header(SYNTHETIC_HEADER_FRESH, &self.synthetic_id);
173-
req.set_header(SYNTHETIC_HEADER_TRUSTED_SERVER, &id);
174+
req.set_header(HEADER_SYNTHETIC_FRESH, &self.synthetic_id);
175+
req.set_header(HEADER_SYNTHETIC_TRUSTED_SERVER, &id);
174176

175177
println!(
176178
"Sending prebid request with Fresh ID: {} and Trusted Server ID: {}",
@@ -211,10 +213,10 @@ mod tests {
211213
fn test_prebid_request_new_with_full_headers() {
212214
let settings = create_test_settings();
213215
let mut req = Request::get("https://example.com/test");
214-
req.set_header(SYNTHETIC_HEADER_TRUSTED_SERVER, "existing-synthetic-id");
216+
req.set_header(HEADER_SYNTHETIC_TRUSTED_SERVER, "existing-synthetic-id");
215217
req.set_header(header::REFERER, "https://test-domain.com/page");
216218
req.set_header(header::ORIGIN, "https://test-domain.com");
217-
req.set_header("X-Forwarded-For", "192.168.1.1, 10.0.0.1");
219+
req.set_header(HEADER_X_FORWARDED_FOR, "192.168.1.1, 10.0.0.1");
218220

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

@@ -280,7 +282,7 @@ mod tests {
280282
fn test_prebid_request_x_forwarded_for_parsing() {
281283
let settings = create_test_settings();
282284
let mut req = Request::get("https://example.com/test");
283-
req.set_header("X-Forwarded-For", "192.168.1.1, 10.0.0.1, 172.16.0.1");
285+
req.set_header(HEADER_X_FORWARDED_FOR, "192.168.1.1, 10.0.0.1, 172.16.0.1");
284286

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

@@ -330,7 +332,7 @@ mod tests {
330332

331333
// Test with empty X-Forwarded-For
332334
let mut req = Request::get("https://example.com/test");
333-
req.set_header("X-Forwarded-For", "");
335+
req.set_header(HEADER_X_FORWARDED_FOR, "");
334336
let prebid_req = PrebidRequest::new(&settings, &req).unwrap();
335337
assert!(!prebid_req.client_ip.is_empty() || prebid_req.client_ip.is_empty());
336338

crates/common/src/synthetic.rs

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use hmac::{Hmac, Mac};
55
use serde_json::json;
66
use sha2::Sha256;
77

8-
use crate::constants::{SYNTHETIC_HEADER_PUB_USER_ID, SYNTHETIC_HEADER_TRUSTED_SERVER};
8+
use crate::constants::{HEADER_SYNTHETIC_PUB_USER_ID, HEADER_SYNTHETIC_TRUSTED_SERVER};
99
use crate::cookies::handle_request_cookies;
1010
use crate::settings::Settings;
1111

@@ -21,7 +21,7 @@ pub fn generate_synthetic_id(settings: &Settings, req: &Request) -> String {
2121
.map(|cookie| cookie.value().to_string())
2222
});
2323
let auth_user_id = req
24-
.get_header(SYNTHETIC_HEADER_PUB_USER_ID)
24+
.get_header(HEADER_SYNTHETIC_PUB_USER_ID)
2525
.map(|h| h.to_str().unwrap_or("anonymous"));
2626
let publisher_domain = req
2727
.get_header(header::HOST)
@@ -61,7 +61,7 @@ pub fn generate_synthetic_id(settings: &Settings, req: &Request) -> String {
6161
pub fn get_or_generate_synthetic_id(settings: &Settings, req: &Request) -> String {
6262
// First try to get existing Trusted Server ID from header
6363
if let Some(synthetic_id) = req
64-
.get_header(SYNTHETIC_HEADER_TRUSTED_SERVER)
64+
.get_header(HEADER_SYNTHETIC_TRUSTED_SERVER)
6565
.and_then(|h| h.to_str().ok())
6666
.map(|s| s.to_string())
6767
{
@@ -96,9 +96,10 @@ pub fn get_or_generate_synthetic_id(settings: &Settings, req: &Request) -> Strin
9696
#[cfg(test)]
9797
mod tests {
9898
use super::*;
99-
use fastly::http::HeaderValue;
99+
use crate::constants::HEADER_X_PUB_USER_ID;
100+
use fastly::http::{HeaderName, HeaderValue};
100101

101-
fn create_test_request(headers: Vec<(&str, &str)>) -> Request {
102+
fn create_test_request(headers: Vec<(HeaderName, &str)>) -> Request {
102103
let mut req = Request::new("GET", "http://example.com");
103104
for (key, value) in headers {
104105
req.set_header(key, HeaderValue::from_str(value).unwrap());
@@ -129,11 +130,11 @@ mod tests {
129130
fn test_generate_synthetic_id() {
130131
let settings: Settings = create_settings();
131132
let req = create_test_request(vec![
132-
(header::USER_AGENT.as_ref(), "Mozilla/5.0"),
133-
(header::COOKIE.as_ref(), "pub_userid=12345"),
134-
("X-Pub-User-ID", "67890"),
135-
(header::HOST.as_ref(), "example.com"),
136-
(header::ACCEPT_LANGUAGE.as_ref(), "en-US,en;q=0.9"),
133+
(header::USER_AGENT, "Mozilla/5.0"),
134+
(header::COOKIE, "pub_userid=12345"),
135+
(HEADER_X_PUB_USER_ID, "67890"),
136+
(header::HOST, "example.com"),
137+
(header::ACCEPT_LANGUAGE, "en-US,en;q=0.9"),
137138
]);
138139

139140
let synthetic_id = generate_synthetic_id(&settings, &req);
@@ -148,7 +149,7 @@ mod tests {
148149
fn test_get_or_generate_synthetic_id_with_header() {
149150
let settings = create_settings();
150151
let req = create_test_request(vec![(
151-
SYNTHETIC_HEADER_TRUSTED_SERVER,
152+
HEADER_SYNTHETIC_TRUSTED_SERVER,
152153
"existing_synthetic_id",
153154
)]);
154155

@@ -159,10 +160,7 @@ mod tests {
159160
#[test]
160161
fn test_get_or_generate_synthetic_id_with_cookie() {
161162
let settings = create_settings();
162-
let req = create_test_request(vec![(
163-
header::COOKIE.as_ref(),
164-
"synthetic_id=existing_cookie_id",
165-
)]);
163+
let req = create_test_request(vec![(header::COOKIE, "synthetic_id=existing_cookie_id")]);
166164

167165
let synthetic_id = get_or_generate_synthetic_id(&settings, &req);
168166
assert_eq!(synthetic_id, "existing_cookie_id");

0 commit comments

Comments
 (0)