Architecture
Mocktioneer is built on EdgeZero, an adapter-agnostic framework for edge computing. This architecture allows the same application logic to run across multiple platforms.
Workspace Layout
mocktioneer/
├── Cargo.toml # Workspace manifest
├── edgezero.toml # EdgeZero configuration
├── crates/
│ ├── mocktioneer-core/ # Shared business logic
│ ├── mocktioneer-adapter-axum/ # Native HTTP server
│ ├── mocktioneer-adapter-fastly/ # Fastly Compute binary
│ └── mocktioneer-adapter-cloudflare/ # Cloudflare Workers binary
└── examples/ # Helper scriptsEdgeZero is consumed via git dependencies (see Cargo.toml).
Crate Responsibilities
mocktioneer-core
The core crate contains all shared logic:
mocktioneer-core/
├── src/
│ ├── lib.rs # App entrypoint, exports modules
│ ├── routes.rs # HTTP handlers
│ ├── openrtb.rs # OpenRTB types and parsing
│ ├── aps.rs # APS TAM types and parsing
│ ├── auction.rs # Bid generation logic
│ ├── mediation.rs # Auction mediation
│ ├── render.rs # HTML/SVG rendering
│ └── verification.rs # Request signature verification
├── static/
│ ├── pixel.gif # 1x1 transparent GIF
│ └── templates/ # Handlebars templates
└── tests/
├── endpoints.rs # Integration tests
└── aps_endpoints.rsAdapter Crates
Each adapter crate is minimal - it just wires up the EdgeZero runtime:
// mocktioneer-adapter-axum/src/main.rs
fn main() {
edgezero_adapter_axum::serve(mocktioneer_core::build_app());
}The adapter crates handle platform-specific concerns:
- Request/response translation
- Runtime initialization
- Platform-specific logging
EdgeZero Integration
App Macro
The core crate uses the edgezero_core::app! macro to generate the app structure:
edgezero_core::app!("../../edgezero.toml", MocktioneerApp);This macro:
- Parses
edgezero.tomlat compile time - Generates route registration code
- Creates the
MocktioneerApptype with abuild_app()method
Middleware
Middleware is applied to all routes in order:
- RequestLogger - Logs incoming requests
- Cors - Adds CORS headers to responses
Request Context
Handlers receive a RequestContext that provides:
- Request body and headers
- Path parameters
- Query string parsing
- Validated JSON extraction
Data Flow
┌─────────────────┐
│ HTTP Request │
└────────┬────────┘
│
▼
┌─────────────────┐
│ Adapter │ Platform-specific request handling
└────────┬────────┘
│
▼
┌─────────────────┐
│ Middleware │ Logging, CORS
└────────┬────────┘
│
▼
┌─────────────────┐
│ Router │ Match path to handler
└────────┬────────┘
│
▼
┌─────────────────┐
│ Handler │ Business logic in mocktioneer-core
└────────┬────────┘
│
▼
┌─────────────────┐
│ Response │ JSON, HTML, or binary
└─────────────────┘Module Details
routes.rs
HTTP handlers for all endpoints. Uses extractors for type-safe request parsing:
#[action]
pub async fn handle_openrtb_auction(
RequestContext(ctx): RequestContext,
ForwardedHost(host): ForwardedHost,
ValidatedJson(req): ValidatedJson<OpenRTBRequest>,
) -> Result<Response, EdgeError> {
// ...
}openrtb.rs
OpenRTB 2.x type definitions with serde serialization:
OpenRTBRequest- Bid request structureOpenRTBResponse- Bid response structureImpression,Banner,Bid, etc.
auction.rs
Bid generation logic:
build_openrtb_response()- Generate bids for OpenRTBbuild_aps_response()- Generate bids for APS TAMis_standard_size()- Check if dimensions are supported
render.rs
Template rendering:
render_svg()- Generate SVG creative with size/bid badgecreative_html()- Generate HTML wrapper for creativeinfo_html()- Generate service info page
Supported Sizes
Mocktioneer supports 13 standard IAB ad sizes, each with a fixed CPM price. See the full size list with pricing in the API reference.
Non-standard sizes return 404 for static assets or are coerced to 300x250 for auction responses. Use the /_/sizes endpoint to get the current list programmatically.