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
3 changes: 3 additions & 0 deletions .github/workflows/format.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ jobs:
- name: Run cargo fmt
uses: actions-rust-lang/rustfmt@v1

- name: Install protoc
run: sudo apt-get install -y protobuf-compiler

- name: Run cargo clippy
run: cargo clippy --all-targets --all-features -- -D warnings

Expand Down
3 changes: 3 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ jobs:
if: steps.cache-viceroy.outputs.cache-hit != 'true'
run: cargo install --git https://github.com/fastly/Viceroy viceroy

- name: Install protoc
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📌 CI protoc install is uncached and somewhat fragile

apt-get install -y protobuf-compiler runs without apt-get update and uncached on every build. This usually works but can intermittently fail on runner image changes. Since the proto file changes rarely, consider:

  1. Checking in the generated .rs file and only regenerating via a script — eliminates this dependency entirely.
  2. Or at minimum, caching the apt install or using a setup action.

run: sudo apt-get install -y protobuf-compiler

- name: Run tests
run: cargo test

Expand Down
114 changes: 114 additions & 0 deletions Cargo.lock

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

3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ members = [
"crates/common",
"crates/fastly",
"crates/js",
"crates/openrtb",
]

# Build defaults exclude the web-only tsjs crate, which is compiled via wasm-pack.
Expand Down Expand Up @@ -65,6 +66,8 @@ lol_html = "2.7.1"
once_cell = "1.21"
matchit = "0.9"
pin-project-lite = "0.2"
prost = "0.13"
prost-build = "0.13"
rand = "0.8"
regex = "1.12.3"
serde = { version = "1.0", features = ["derive"] }
Expand Down
1 change: 1 addition & 0 deletions crates/common/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ sha2 = { workspace = true }
tokio = { workspace = true }
toml = { workspace = true }
trusted-server-js = { path = "../js" }
trusted-server-openrtb = { path = "../openrtb" }
url = { workspace = true }
urlencoding = { workspace = true }
uuid = { workspace = true }
Expand Down
54 changes: 43 additions & 11 deletions crates/common/src/auction/formats.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use crate::auction::context::ContextValue;
use crate::creative;
use crate::error::TrustedServerError;
use crate::geo::GeoInfo;
use crate::openrtb::{OpenRtbBid, OpenRtbResponse, ResponseExt, SeatBid};
use crate::openrtb::{OpenRtbBid, OpenRtbResponse, ResponseExt, SeatBid, ToExt};
use crate::settings::Settings;
use crate::synthetic::{generate_synthetic_id, get_or_generate_synthetic_id};

Expand Down Expand Up @@ -205,7 +205,7 @@ pub fn convert_to_openrtb_response(
auction_request: &AuctionRequest,
) -> Result<Response, Report<TrustedServerError>> {
// Build OpenRTB-style seatbid array
let mut seatbids = Vec::new();
let mut seatbids = Vec::with_capacity(result.winning_bids.len());

for (slot_id, bid) in &result.winning_bids {
let price = bid.price.ok_or_else(|| {
Expand All @@ -217,6 +217,34 @@ pub fn convert_to_openrtb_response(
})
})?;

let width = match i32::try_from(bid.width) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔧 Duplicated u32 → i32 conversion logic

This inline match i32::try_from(...) is identical in structure to to_openrtb_i32() in prebid.rs:468-481. The only difference is the log message format.

Suggestion: Move to_openrtb_i32 (or a variant that takes a context string) to the openrtb module or a shared utility, and use it from both call sites. This also reduces the line count here significantly — the width + height blocks are 26 lines that could be 2.

Ok(converted) => Some(converted),
Err(_) => {
log::warn!(
"Auction response: omitting bid width for auction {} slot {} bidder {} because width {} exceeds i32::MAX",
auction_request.id,
slot_id,
bid.bidder,
bid.width
);
None
}
};

let height = match i32::try_from(bid.height) {
Ok(converted) => Some(converted),
Err(_) => {
log::warn!(
"Auction response: omitting bid height for auction {} slot {} bidder {} because height {} exceeds i32::MAX",
auction_request.id,
slot_id,
bid.bidder,
bid.height
);
None
}
};

// Process creative HTML if present - rewrite URLs and return inline
let creative_html = if let Some(ref raw_creative) = bid.creative {
// Rewrite creative HTML with proxy URLs for first-party delivery
Expand All @@ -241,19 +269,21 @@ pub fn convert_to_openrtb_response(
};

let openrtb_bid = OpenRtbBid {
id: format!("{}-{}", bid.bidder, slot_id),
impid: slot_id.to_string(),
price,
id: Some(format!("{}-{}", bid.bidder, slot_id)),
impid: Some(slot_id.to_string()),
price: Some(price),
adm: Some(creative_html),
crid: Some(format!("{}-creative", bid.bidder)),
w: Some(bid.width),
h: Some(bid.height),
adomain: Some(bid.adomain.clone().unwrap_or_default()),
w: width,
h: height,
adomain: bid.adomain.clone().unwrap_or_default(),
..Default::default()
};

seatbids.push(SeatBid {
seat: Some(bid.bidder.clone()),
bid: vec![openrtb_bid],
..Default::default()
});
}

Expand All @@ -272,17 +302,19 @@ pub fn convert_to_openrtb_response(
.collect();

let response_body = OpenRtbResponse {
id: auction_request.id.to_string(),
id: Some(auction_request.id.to_string()),
seatbid: seatbids,
ext: Some(ResponseExt {
ext: ResponseExt {
orchestrator: OrchestratorExt {
strategy: strategy_name.to_string(),
providers: result.provider_responses.len(),
total_bids: result.total_bids(),
time_ms: result.total_time_ms,
provider_details,
},
}),
}
.to_ext(),
..Default::default()
};

let body_bytes =
Expand Down
Loading