Skip to content
Merged
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
42 changes: 42 additions & 0 deletions .github/workflows/format.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
name: "Run Format"

on:
push:
branches: [main]
pull_request:
branches: [main]

# Check formatting with rustfmt
jobs:
format:
name: cargo fmt
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Cache cargo dependencies
uses: actions/cache@v4
with:
path: |
~/.cargo/bin/
~/.cargo/registry/index/
~/.cargo/registry/cache/
~/.cargo/git/db/
target/
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}

- name: Set up rust toolchain
uses: actions-rust-lang/setup-rust-toolchain@v1
with:
components: "clippy, rustfmt"
toolchain: 1.83

- name: Add wasm32-wasi target
run: rustup target add wasm32-wasip1

- name: Run cargo fmt
uses: actions-rust-lang/rustfmt@v1

- name: Run cargo clipply
run: cargo clippy --all-targets --all-features

39 changes: 39 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
name: "Run Tests"

on:
push:
branches: [main]
pull_request:
branches: [main]

jobs:
test:
name: cargo test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Cache Cargo dependencies
uses: actions/cache@v4
with:
path: |
~/.cargo/bin/
~/.cargo/registry/index/
~/.cargo/registry/cache/
~/.cargo/git/db/
target/
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}

- name: Set up Rust tool chain
uses: actions-rust-lang/setup-rust-toolchain@v1
with:
toolchain: 1.83

- name: Add wasm32-wasi target
run: rustup target add wasm32-wasip1

- name: Setup Viceroy
run: cargo install viceroy

- name: Run tests
run: cargo test
1 change: 0 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ edition = "2021"
# Otherwise, `publish = false` prevents an accidental `cargo publish` from revealing private source.
publish = false
license = "Apache-2.0"
license-file = "LICENSE"

[profile.release]
debug = 1
Expand Down
19 changes: 9 additions & 10 deletions src/cookies.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
use cookie::{Cookie, CookieJar};
use fastly::http::header;
use fastly::Request;
use log;

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

// return empty cookie jar for unparsable cookies
pub fn parse_cookies_to_jar(s: &str) -> CookieJar {
Expand Down Expand Up @@ -80,8 +79,8 @@ mod tests {

#[test]
fn test_handle_request_cookies() {
let mut req = Request::get("http://example.com").with_header(header::COOKIE, "c1=v1;c2=v2");
let jar = handle_request_cookies(&mut req).unwrap();
let req = Request::get("http://example.com").with_header(header::COOKIE, "c1=v1;c2=v2");
let jar = handle_request_cookies(&req).unwrap();

assert!(jar.iter().count() == 2);
assert_eq!(jar.get("c1").unwrap().value(), "v1");
Expand All @@ -90,24 +89,24 @@ mod tests {

#[test]
fn test_handle_request_cookies_with_empty_cookie() {
let mut req = Request::get("http://example.com").with_header(header::COOKIE, "");
let jar = handle_request_cookies(&mut req).unwrap();
let req = Request::get("http://example.com").with_header(header::COOKIE, "");
let jar = handle_request_cookies(&req).unwrap();

assert!(jar.iter().count() == 0);
}

#[test]
fn test_handle_request_cookies_no_cookie_header() {
let mut req: Request = Request::get("https://example.com");
let jar = handle_request_cookies(&mut req);
let req: Request = Request::get("https://example.com");
let jar = handle_request_cookies(&req);

assert!(jar.is_none());
}

#[test]
fn test_handle_request_cookies_invalid_cookie_header() {
let mut req = Request::get("http://example.com").with_header(header::COOKIE, "invalid");
let jar = handle_request_cookies(&mut req).unwrap();
let req = Request::get("http://example.com").with_header(header::COOKIE, "invalid");
let jar = handle_request_cookies(&req).unwrap();

assert!(jar.iter().count() == 0);
}
Expand Down
15 changes: 9 additions & 6 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,22 +129,22 @@ fn handle_ad_request(settings: &Settings, req: Request) -> Result<Response, Erro
println!("Fetching current count for synthetic ID: {}", synthetic_id);
let current_count: i32 = store
.lookup(&synthetic_id)
.and_then(|mut val| {
.map(|mut val| {
// Convert LookupResponse to bytes first
match String::from_utf8(val.take_body_bytes()) {
Ok(s) => {
println!("Value from KV store: {}", s);
Ok(Some(s))
Some(s)
}
Err(e) => {
println!("Error converting bytes to string: {}", e);
Ok(None)
None
}
}
})
.and_then(|opt_s| {
.map(|opt_s| {
println!("Parsing string value: {:?}", opt_s);
Ok(opt_s.and_then(|s| s.parse().ok()))
opt_s.and_then(|s| s.parse().ok())
})
.unwrap_or_else(|_| {
println!("No existing count found, starting at 0");
Expand All @@ -163,7 +163,10 @@ fn handle_ad_request(settings: &Settings, req: Request) -> Result<Response, Erro
println!("Synthetic ID {} visit count: {}", synthetic_id, new_count);

// Construct URL with synthetic ID
let ad_server_url = settings.ad_server.sync_url.replace("{{synthetic_id}}", &synthetic_id);
let ad_server_url = settings
.ad_server
.sync_url
.replace("{{synthetic_id}}", &synthetic_id);

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

Expand Down
1 change: 0 additions & 1 deletion src/prebid.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
use fastly::http::{header, Method};
use fastly::{Error, Request, Response};
use serde_json::json;
use url;

use crate::constants::{SYNTH_HEADER_FRESH, SYNTH_HEADER_POTSI};
use crate::settings::Settings;
Expand Down
13 changes: 6 additions & 7 deletions src/synthetic.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
use fastly::http::header;
use fastly::Request;
use hmac::{Hmac, Mac};
use log;
use sha2::Sha256;

use crate::constants::SYNTH_HEADER_POTSI;
Expand Down Expand Up @@ -65,7 +64,7 @@ pub fn get_or_generate_synthetic_id(settings: &Settings, req: &Request) -> Strin
return potsi;
}

let req_cookie_jar: Option<cookie::CookieJar> = handle_request_cookies(&req);
let req_cookie_jar: Option<cookie::CookieJar> = handle_request_cookies(req);
match req_cookie_jar {
Some(jar) => {
let potsi_cookie = jar.get("synthetic_id");
Expand Down Expand Up @@ -121,11 +120,11 @@ mod tests {
fn test_generate_synthetic_id() {
let settings: Settings = create_settings();
let req = create_test_request(vec![
(&header::USER_AGENT.to_string(), "Mozilla/5.0"),
(&header::COOKIE.to_string(), "pub_userid=12345"),
(header::USER_AGENT.as_ref(), "Mozilla/5.0"),
(header::COOKIE.as_ref(), "pub_userid=12345"),
("X-Pub-User-ID", "67890"),
(&header::HOST.to_string(), "example.com"),
(&header::ACCEPT_LANGUAGE.to_string(), "en-US,en;q=0.9"),
(header::HOST.as_ref(), "example.com"),
(header::ACCEPT_LANGUAGE.as_ref(), "en-US,en;q=0.9"),
]);

let synthetic_id = generate_synthetic_id(&settings, &req);
Expand All @@ -148,7 +147,7 @@ mod tests {
fn test_get_or_generate_synthetic_id_with_cookie() {
let settings = create_settings();
let req = create_test_request(vec![(
&header::COOKIE.to_string(),
header::COOKIE.as_ref(),
"synthetic_id=existing_cookie_id",
)]);

Expand Down