Skip to content

Commit 6fecf70

Browse files
committed
Merge branch 'main' into feature/init-gh-actions
2 parents f2f3cdb + adfbb16 commit 6fecf70

File tree

8 files changed

+218
-89
lines changed

8 files changed

+218
-89
lines changed

LICENSE

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@
187187
same "printed page" as the copyright notice for easier
188188
identification within third-party archives.
189189

190-
Copyright [yyyy] [name of copyright owner]
190+
Copyright 2018 IAB Technology Laboratory, Inc.
191191

192192
Licensed under the Apache License, Version 2.0 (the "License");
193193
you may not use this file except in compliance with the License.

README.md

Lines changed: 93 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,56 +1,131 @@
1-
# potsi
1+
# Trusted Server
22

3-
# Installation
3+
:information_source: At this time, Trusted Server is designed to work with Fastly. Follow these steps to configure Fastly Compute and deploy it.
44

5-
## Pre-requisites
5+
## Fastly
6+
- Create account at Fastly if you don’t have one - manage.fastly.com
7+
- Log in to the Fastly control panel.
8+
- Go to Account > API tokens > Personal tokens.
9+
- Click Create token
10+
- Name the Token
11+
- Choose User Token
12+
- Choose Global API Access
13+
- Choose what makes sense for your Org in terms of Service Access
14+
- Copy key to a secure location because you will not be able to see it again
15+
16+
- Create new Compute Service
17+
- Click Compute and Create Service
18+
- Click “Create Empty Service” (below main options)
19+
- Add your domain of the website you’ll be testing or using and click update
20+
- Click on “Origins” section and add your ad-server / ssp partner information as hostnames (note after you save this information you can select port numbers and TLS on/off)
21+
- IMPORTANT: when you enter the FQDN or IP ADDR information and click Add you need to enter a “Name” in the first field that will be referenced in your code so something like “my_ad_partner_1”
22+
-
23+
24+
:warning: Fastly gives you a test domain to play on but obviously you’re free to create a CNAME to your domain when you’re ready. Note that Fastly compute ONLY accepts client traffic from TLS
25+
26+
## Installation
27+
28+
### Brew
29+
30+
:warning: Follow the prompts before and afterwards (to configure system path, etc)
31+
32+
#### Install Brew
633

7-
### asdf
834
```sh
9-
brew install asdf
35+
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
1036
```
37+
### Fastly CLI
1138

12-
### Fastly
39+
#### Install Fastly CLI
1340
```sh
1441
brew install fastly/tap/fastly
1542
```
1643

17-
## rust
44+
#### Verify Installation and Version
45+
```sh
46+
fastly version
47+
```
48+
49+
#### Create profile and follow interactive prompt for pasting your API Token created earlier:
50+
```sh
51+
fastly profile create
52+
```
53+
54+
### Rust
55+
56+
#### Install Rust with asdf
1857
```sh
58+
brew install asdf
1959
asdf plugin add rust
2060
asdf install rust 1.83.0
2161
asdf reshim
2262
```
2363

24-
## viceroy (for running tests)
64+
#### Fix path for Bash
65+
66+
Edit ~/.bash_profile to add path for asdf shims:
2567
```sh
26-
cargo install viceroy
68+
export PATH="${ASDF_DATA_DIR:-$HOME/.asdf}/shims:$PATH"
69+
```
70+
71+
#### Fix path for ZSH
72+
73+
Edit ~/.zshrc to add path for asdf shims:
74+
```sh
75+
export PATH="${ASDF_DATA_DIR:-$HOME/.asdf}/shims:$PATH"
2776
```
2877

29-
## Build
78+
#### Other shells
79+
See https://asdf-vm.com/guide/getting-started.html#_2-configure-asdf
80+
81+
82+
### Configure Build and
83+
84+
#### Clone Project
85+
```sh
86+
git clone [email protected]:IABTechLab/trusted-server.git
87+
```
88+
89+
### Configure
90+
#### Edit configuration files
91+
:information_source: Note that you’ll have to edit the following files for your setup:
92+
93+
- fastly.toml (service ID, author, description)
94+
- Potsi.toml (KV store ID names)
95+
96+
### Build
3097

3198
```sh
3299
cargo build
33100
```
34101

35-
## Run
102+
### Deploy to Fastly
36103

37-
### Fastly
38-
- Review configuration for [local_server](fastly.toml#L16)
104+
```sh
105+
fastly compute publish
106+
```
39107

40-
- Run it with
108+
## Devleopment
41109

110+
#### Install viceroy for running tests
42111
```sh
43-
fastly -i compute serve
112+
cargo install viceroy
44113
```
45114

46-
## Test
115+
#### Run Fastly server locally
116+
Review configuration for [local_server](fastly.toml#L16)
117+
```sh
118+
fastly -i compute serve
47119
```
120+
121+
#### Tests
122+
```sh
48123
cargo test
49124
```
50125

51-
Note: if test fails `viceroy` will not display line number of the failed test. Rerun it with `cargo test_details`.
126+
:warning: if test fails `viceroy` will not display line number of the failed test. Rerun it with `cargo test_details`.
52127

53-
## Additional Rust Commands
128+
#### Additional Rust Commands
54129
- `cargo fmt`: Ensure uniform code formatting
55130
- `cargo clippy`: Ensure idiomatic code
56131
- `cargo check`: Ensure compilation succeeds on Linux, MacOS, Windows and WebAssembly

potsi.toml

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,11 @@
1+
[ad_server]
2+
ad_partner_url = "equativ_ad_api_2"
3+
sync_url = "https://adapi-srv-eu.smartadserver.com/ac?pgid=2040327&fmtid=137675&synthetic_id={{synthetic_id}}"
4+
5+
[prebid]
6+
server_url = "http://68.183.113.79:8000/openrtb2/auction"
7+
18
[synthetic]
29
counter_store = "jevans_synth_id_counter"
3-
opid_store = "jevans_synth_id_opid"
10+
opid_store = "jevans_synth_id_opid"
11+
secret_key = "potsi"

src/constants.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,2 @@
1-
pub const BACKEND2: &str = "equativ_ad_api_2";
2-
pub const SECRET_KEY: &[u8] = b"stackpop";
3-
pub const SYNTH_ID_COUNTER_STORE: &str = "jevans_synth_id_counter";
4-
pub const SYNTH_ID_OPID_STORE: &str = "jevans_synth_id_opid";
1+
pub const SYNTH_HEADER_FRESH: &str = "X-Synthetic-Fresh";
2+
pub const SYNTH_HEADER_POTSI: &str = "X-Synthetic-Potsi";

src/main.rs

Lines changed: 38 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use std::env;
77

88
mod constants;
99
mod cookies;
10-
use constants::*;
10+
use constants::{SYNTH_HEADER_FRESH, SYNTH_HEADER_POTSI};
1111
mod models;
1212
use models::AdResponse;
1313
mod prebid;
@@ -21,44 +21,46 @@ use templates::HTML_TEMPLATE;
2121

2222
#[fastly::main]
2323
fn main(req: Request) -> Result<Response, Error> {
24-
let _settings = Settings::new();
24+
let settings = Settings::new().unwrap();
25+
println!("Settings {settings:?}");
26+
2527
futures::executor::block_on(async {
2628
println!(
2729
"FASTLY_SERVICE_VERSION: {}",
2830
std::env::var("FASTLY_SERVICE_VERSION").unwrap_or_else(|_| String::new())
2931
);
3032

3133
match (req.get_method(), req.get_path()) {
32-
(&Method::GET, "/") => handle_main_page(req),
33-
(&Method::GET, "/ad-creative") => handle_ad_request(req),
34-
(&Method::GET, "/prebid-test") => handle_prebid_test(req).await,
34+
(&Method::GET, "/") => handle_main_page(&settings, req),
35+
(&Method::GET, "/ad-creative") => handle_ad_request(&settings, req),
36+
(&Method::GET, "/prebid-test") => handle_prebid_test(&settings, req).await,
3537
_ => Ok(Response::from_status(StatusCode::NOT_FOUND)
3638
.with_body("Not Found")
3739
.with_header(header::CONTENT_TYPE, "text/plain")),
3840
}
3941
})
4042
}
4143

42-
fn handle_main_page(req: Request) -> Result<Response, Error> {
44+
fn handle_main_page(settings: &Settings, req: Request) -> Result<Response, Error> {
4345
println!(
44-
"Testing constants - BACKEND2: {}, SYNTH_ID_COUNTER_STORE: {}",
45-
BACKEND2, SYNTH_ID_COUNTER_STORE
46+
"Using ad_partner_url: {}, counter_store: {}",
47+
settings.ad_server.ad_partner_url, settings.synthetic.counter_store,
4648
);
4749

4850
log_fastly::init_simple("mylogs", Info);
4951

5052
// Calculate fresh ID first using the synthetic module
51-
let fresh_id = synthetic::generate_synthetic_id(&req);
53+
let fresh_id = synthetic::generate_synthetic_id(settings, &req);
5254

5355
// Check for existing POTSI ID in this specific order:
5456
// 1. X-Synthetic-Potsi header
5557
// 2. Cookie
5658
// 3. Fall back to fresh ID
57-
let synthetic_id = synthetic::get_or_generate_synthetic_id(&req);
59+
let synthetic_id = synthetic::get_or_generate_synthetic_id(settings, &req);
5860

5961
println!(
6062
"Existing POTSI header: {:?}",
61-
req.get_header("X-Synthetic-Potsi")
63+
req.get_header(SYNTH_HEADER_POTSI)
6264
);
6365
println!("Generated Fresh ID: {}", fresh_id);
6466
println!("Using POTSI ID: {}", synthetic_id);
@@ -67,8 +69,8 @@ fn handle_main_page(req: Request) -> Result<Response, Error> {
6769
let mut response = Response::from_status(StatusCode::OK)
6870
.with_body(HTML_TEMPLATE)
6971
.with_header(header::CONTENT_TYPE, "text/html")
70-
.with_header("X-Synthetic-Fresh", &fresh_id) // Fresh ID always changes
71-
.with_header("X-Synthetic-Potsi", &synthetic_id); // POTSI ID remains stable
72+
.with_header(SYNTH_HEADER_FRESH, &fresh_id) // Fresh ID always changes
73+
.with_header(SYNTH_HEADER_POTSI, &synthetic_id); // POTSI ID remains stable
7274

7375
// Always set the cookie with the synthetic ID
7476
response.set_header(
@@ -94,7 +96,7 @@ fn handle_main_page(req: Request) -> Result<Response, Error> {
9496
Ok(response)
9597
}
9698

97-
fn handle_ad_request(req: Request) -> Result<Response, Error> {
99+
fn handle_ad_request(settings: &Settings, req: Request) -> Result<Response, Error> {
98100
// Log headers for debugging
99101
let client_ip = req
100102
.get_client_ip_addr()
@@ -108,11 +110,11 @@ fn handle_ad_request(req: Request) -> Result<Response, Error> {
108110
println!("X-Forwarded-For: {}", x_forwarded_for.unwrap_or("None"));
109111

110112
// Generate synthetic ID
111-
let synthetic_id = generate_synthetic_id(&req);
113+
let synthetic_id = generate_synthetic_id(settings, &req);
112114

113115
// Increment visit counter in KV store
114-
println!("Opening KV store: {}", SYNTH_ID_COUNTER_STORE);
115-
let store = match KVStore::open(SYNTH_ID_COUNTER_STORE) {
116+
println!("Opening KV store: {}", settings.synthetic.counter_store);
117+
let store = match KVStore::open(settings.synthetic.counter_store.as_str()) {
116118
Ok(Some(store)) => store,
117119
Ok(None) => {
118120
println!("KV store not found");
@@ -161,10 +163,7 @@ fn handle_ad_request(req: Request) -> Result<Response, Error> {
161163
println!("Synthetic ID {} visit count: {}", synthetic_id, new_count);
162164

163165
// Construct URL with synthetic ID
164-
let ad_server_url = format!(
165-
"https://adapi-srv-eu.smartadserver.com/ac?pgid=2040327&fmtid=137675&synthetic_id={}",
166-
synthetic_id
167-
);
166+
let ad_server_url = settings.ad_server.sync_url.replace("{{synthetic_id}}", &synthetic_id);
168167

169168
println!("Sending request to backend: {}", ad_server_url);
170169

@@ -175,7 +174,7 @@ fn handle_ad_request(req: Request) -> Result<Response, Error> {
175174
println!(" {}: {:?}", name, value);
176175
}
177176

178-
match req.send(BACKEND2) {
177+
match req.send(settings.ad_server.ad_partner_url.as_str()) {
179178
Ok(mut res) => {
180179
println!(
181180
"Received response from backend with status: {}",
@@ -236,8 +235,11 @@ fn handle_ad_request(req: Request) -> Result<Response, Error> {
236235
println!("Found opid: {}", opid);
237236

238237
// Store in opid KV store
239-
println!("Attempting to open KV store: {}", SYNTH_ID_OPID_STORE);
240-
match KVStore::open(SYNTH_ID_OPID_STORE) {
238+
println!(
239+
"Attempting to open KV store: {}",
240+
settings.synthetic.opid_store
241+
);
242+
match KVStore::open(settings.synthetic.opid_store.as_str()) {
241243
Ok(Some(store)) => {
242244
println!("Successfully opened KV store");
243245
match store.insert(&synthetic_id, opid.as_bytes()) {
@@ -251,12 +253,15 @@ fn handle_ad_request(req: Request) -> Result<Response, Error> {
251253
}
252254
}
253255
Ok(None) => {
254-
println!("KV store returned None: {}", SYNTH_ID_OPID_STORE);
256+
println!(
257+
"KV store returned None: {}",
258+
settings.synthetic.opid_store
259+
);
255260
}
256261
Err(e) => {
257262
println!(
258263
"Error opening KV store '{}': {:?}",
259-
SYNTH_ID_OPID_STORE, e
264+
settings.synthetic.opid_store, e
260265
);
261266
}
262267
};
@@ -293,29 +298,29 @@ fn handle_ad_request(req: Request) -> Result<Response, Error> {
293298
}
294299

295300
/// Handles the prebid test route with detailed error logging
296-
async fn handle_prebid_test(mut req: Request) -> Result<Response, Error> {
301+
async fn handle_prebid_test(settings: &Settings, mut req: Request) -> Result<Response, Error> {
297302
println!("Starting prebid test request handling");
298303

299304
// Calculate fresh ID
300-
let fresh_id = synthetic::generate_synthetic_id(&req);
305+
let fresh_id = synthetic::generate_synthetic_id(settings, &req);
301306

302307
// Check for existing POTSI ID in same order as handle_main_page
303-
let synthetic_id = synthetic::get_or_generate_synthetic_id(&req);
308+
let synthetic_id = synthetic::get_or_generate_synthetic_id(settings, &req);
304309

305310
println!(
306311
"Existing POTSI header: {:?}",
307-
req.get_header("X-Synthetic-Potsi")
312+
req.get_header(SYNTH_HEADER_POTSI)
308313
);
309314
println!("Generated Fresh ID: {}", fresh_id);
310315
println!("Using POTSI ID: {}", synthetic_id);
311316

312317
// Set both IDs as headers
313-
req.set_header("X-Synthetic-Fresh", &fresh_id);
314-
req.set_header("X-Synthetic-Potsi", &synthetic_id);
318+
req.set_header(SYNTH_HEADER_FRESH, &fresh_id);
319+
req.set_header(SYNTH_HEADER_POTSI, &synthetic_id);
315320

316321
println!("Using POTSI ID: {}, Fresh ID: {}", synthetic_id, fresh_id);
317322

318-
let prebid_req = match PrebidRequest::new(&req) {
323+
let prebid_req = match PrebidRequest::new(settings, &req) {
319324
Ok(req) => {
320325
println!(
321326
"Successfully created PrebidRequest with synthetic ID: {}",

0 commit comments

Comments
 (0)