Skip to content

Commit c3fbfd1

Browse files
committed
feat(ads-client): add per-request OHTTP support
Add per-request OHTTP support via the `ohttp` flag on `MozAdsRequestOptions` and `MozAdsCallbackOptions`. When enabled, individual MARS requests are routed through viaduct's OHTTP layer with automatic preflight for geo/user-agent override headers. - Add `ohttp: bool` parameter to fetch_ads, record_click, record_impression, report_ad and all public API methods - Add `MozAdsCallbackOptions` FFI type for callback OHTTP support - Add `mars/preflight.rs` with PreflightRequest/PreflightResponse types - Preflight responses cached via HttpCache (CacheFirst with default TTL) - Add `FetchAdsError::Preflight` variant for preflight failures - Add OHTTP integration test against prod - Update usage docs for all platforms (JavaScript, Kotlin, Swift)
1 parent df5c1f2 commit c3fbfd1

File tree

15 files changed

+389
-61
lines changed

15 files changed

+389
-61
lines changed

.github/workflows/ads-client-tests.yaml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,5 +24,21 @@ jobs:
2424
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
2525
source $HOME/.cargo/env
2626
rustup toolchain install
27+
- name: Build NSS
28+
env:
29+
NSS_DIR: ${{ github.workspace }}/libs/desktop/linux-x86-64/nss
30+
NSS_STATIC: 1
31+
run: |
32+
sudo apt-get update
33+
sudo apt-get install -y ninja-build zlib1g-dev tclsh python3
34+
python3 -m venv venv
35+
source venv/bin/activate
36+
python3 -m pip install --upgrade pip setuptools six
37+
git clone https://chromium.googlesource.com/external/gyp.git tools/gyp
38+
cd tools/gyp && pip install . && cd ../..
39+
./libs/verify-desktop-environment.sh
2740
- name: Run ads-client integration tests against MARS staging
41+
env:
42+
NSS_DIR: ${{ github.workspace }}/libs/desktop/linux-x86-64/nss
43+
NSS_STATIC: 1
2844
run: cargo test -p ads-client-integration-tests -- --ignored

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@
77

88
## ✨ What's New ✨
99

10+
### Ads Client
11+
- Add per-request OHTTP support via the `ohttp` flag on `MozAdsRequestOptions` and `MozAdsCallbackOptions`. When enabled, individual MARS requests are routed through viaduct's OHTTP layer with automatic preflight for geo/user-agent override headers.
12+
1013
### Logins
1114
- New `allow_empty_passwords` feature flag to allow storing logins with empty passwords. This feature is intended to be enabled on desktop during the migration.
1215
- Add `ignore_form_action_origin_validation_errors` feature flag that allows logins with non-URL `form_action_origin` values (e.g. "email", "UserCode") to be imported without error. URL normalization for valid URLs is still applied.

components/ads-client/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ once_cell = "1.5"
2727
uniffi = { version = "0.31" }
2828
url = { version = "2", features = ["serde"] }
2929
uuid = { version = "1.3", features = ["v4"] }
30-
viaduct = { path = "../viaduct" }
30+
viaduct = { path = "../viaduct", features = ["ohttp"] }
3131
sql-support = { path = "../support/sql" }
3232

3333
[dev-dependencies]

components/ads-client/docs/usage-javascript.md

Lines changed: 39 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,9 @@ const client = MozAdsClientBuilder()
3737
| Method | Return Type | Description |
3838
| ----------------------------------------------------------------------------------- | ----------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
3939
| `clearCache()` | `void` | Clears the client's HTTP cache. Throws on failure. |
40-
| `recordClick(clickUrl)` | `void` | Records a click using the provided callback URL (typically from `ad.callbacks.click`). |
41-
| `recordImpression(impressionUrl)` | `void` | Records an impression using the provided callback URL (typically from `ad.callbacks.impression`). |
42-
| `reportAd(reportUrl)` | `void` | Reports an ad using the provided callback URL (typically from `ad.callbacks.report`). |
40+
| `recordClick(clickUrl, options?)` | `void` | Records a click using the provided callback URL (typically from `ad.callbacks.click`). Optional `MozAdsCallbackOptions` can enable OHTTP. |
41+
| `recordImpression(impressionUrl, options?)` | `void` | Records an impression using the provided callback URL (typically from `ad.callbacks.impression`). Optional `MozAdsCallbackOptions` can enable OHTTP. |
42+
| `reportAd(reportUrl, reason, options?)` | `void` | Reports an ad using the provided callback URL (typically from `ad.callbacks.report`). Optional `MozAdsCallbackOptions` can enable OHTTP. |
4343
| `requestImageAds(mozAdRequests, options?)` | `Object.<string, MozAdsImage>` | Requests one image ad per placement. Optional `MozAdsRequestOptions` can adjust caching behavior. Returns an object keyed by `placementId`. |
4444
| `requestSpocAds(mozAdRequests, options?)` | `Object.<string, Array.<MozAdsSpoc>>` | Requests spoc ads per placement. Each placement request specifies its own count. Optional `MozAdsRequestOptions` can adjust caching behavior. Returns an object keyed by `placementId`. |
4545
| `requestTileAds(mozAdRequests, options?)` | `Object.<string, MozAdsTile>` | Requests one tile ad per placement. Optional `MozAdsRequestOptions` can adjust caching behavior. Returns an object keyed by `placementId`. |
@@ -246,12 +246,48 @@ Options passed when making a single ad request.
246246
/**
247247
* @typedef {Object} MozAdsRequestOptions
248248
* @property {MozAdsRequestCachePolicy|null} cachePolicy - Per-request caching policy.
249+
* @property {boolean} ohttp - Whether to route this request through OHTTP (default: false).
249250
*/
250251
```
251252

252253
| Field | Type | Description |
253254
| -------------- | ------------------------------------- | ----------------------------------------------------------------------------------------------- |
254255
| `cachePolicy` | `MozAdsRequestCachePolicy \| null` | Per-request caching policy. If `null`, uses the client's default TTL with a `CacheFirst` mode. |
256+
| `ohttp` | `boolean` | Whether to route this request through OHTTP. Defaults to `false`. |
257+
258+
---
259+
260+
## `MozAdsCallbackOptions`
261+
262+
Options passed when making callback requests (click, impression, report).
263+
264+
```javascript
265+
/**
266+
* @typedef {Object} MozAdsCallbackOptions
267+
* @property {boolean} ohttp - Whether to route this callback through OHTTP (default: false).
268+
*/
269+
```
270+
271+
| Field | Type | Description |
272+
| ------- | --------- | ------------------------------------------------------------------ |
273+
| `ohttp` | `boolean` | Whether to route this callback through OHTTP. Defaults to `false`. |
274+
275+
#### OHTTP Usage Example
276+
277+
```javascript
278+
// Request ads over OHTTP
279+
const ads = client.requestTileAds(placements, {
280+
ohttp: true
281+
});
282+
283+
// Record a click over OHTTP
284+
client.recordClick(ad.callbacks.click, { ohttp: true });
285+
286+
// Record an impression over OHTTP
287+
client.recordImpression(ad.callbacks.impression, { ohttp: true });
288+
```
289+
290+
> **Note:** OHTTP must be configured at the viaduct level before use. When `ohttp` is `true`, the client automatically performs a preflight request to obtain geo-location and user-agent headers, which are injected into the MARS request.
255291
256292
---
257293

components/ads-client/docs/usage-kotlin.md

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,9 @@ val client = MozAdsClientBuilder()
3434
| Method | Return Type | Description |
3535
| ----------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
3636
| `clearCache()` | `Unit` | Clears the client's HTTP cache. Throws on failure. |
37-
| `recordClick(clickUrl: String)` | `Unit` | Records a click using the provided callback URL (typically from `ad.callbacks.click`). |
38-
| `recordImpression(impressionUrl: String)` | `Unit` | Records an impression using the provided callback URL (typically from `ad.callbacks.impression`). |
39-
| `reportAd(reportUrl: String)` | `Unit` | Reports an ad using the provided callback URL (typically from `ad.callbacks.report`). |
37+
| `recordClick(clickUrl: String, options: MozAdsCallbackOptions?)` | `Unit` | Records a click using the provided callback URL (typically from `ad.callbacks.click`). |
38+
| `recordImpression(impressionUrl: String, options: MozAdsCallbackOptions?)` | `Unit` | Records an impression using the provided callback URL (typically from `ad.callbacks.impression`). |
39+
| `reportAd(reportUrl: String, reason: MozAdsReportReason, options: MozAdsCallbackOptions?)` | `Unit` | Reports an ad using the provided callback URL (typically from `ad.callbacks.report`). |
4040
| `requestImageAds(mozAdRequests: List<MozAdsPlacementRequest>, options: MozAdsRequestOptions?)` | `Map<String, MozAdsImage>` | Requests one image ad per placement. Optional `MozAdsRequestOptions` can adjust caching behavior. Returns a map keyed by `placementId`. |
4141
| `requestSpocAds(mozAdRequests: List<MozAdsPlacementRequestWithCount>, options: MozAdsRequestOptions?)` | `Map<String, List<MozAdsSpoc>>` | Requests spoc ads per placement. Each placement request specifies its own count. Optional `MozAdsRequestOptions` can adjust caching behavior. Returns a map keyed by `placementId`. |
4242
| `requestTileAds(mozAdRequests: List<MozAdsPlacementRequest>, options: MozAdsRequestOptions?)` | `Map<String, MozAdsTile>` | Requests one tile ad per placement. Optional `MozAdsRequestOptions` can adjust caching behavior. Returns a map keyed by `placementId`. |
@@ -219,13 +219,46 @@ Options passed when making a single ad request.
219219

220220
```kotlin
221221
data class MozAdsRequestOptions(
222-
val cachePolicy: MozAdsRequestCachePolicy?
222+
val cachePolicy: MozAdsRequestCachePolicy?,
223+
val ohttp: Boolean = false
223224
)
224225
```
225226

226227
| Field | Type | Description |
227228
| -------------- | ---------------------------- | ---------------------------------------------------------------------------------------------- |
228229
| `cachePolicy` | `MozAdsRequestCachePolicy?` | Per-request caching policy. If `null`, uses the client's default TTL with a `CacheFirst` mode. |
230+
| `ohttp` | `Boolean` | Whether to route this request through OHTTP. Defaults to `false`. |
231+
232+
---
233+
234+
## `MozAdsCallbackOptions`
235+
236+
Options passed when making callback requests (click, impression, report).
237+
238+
```kotlin
239+
data class MozAdsCallbackOptions(
240+
val ohttp: Boolean = false
241+
)
242+
```
243+
244+
| Field | Type | Description |
245+
| ------- | --------- | ------------------------------------------------------------------ |
246+
| `ohttp` | `Boolean` | Whether to route this callback through OHTTP. Defaults to `false`. |
247+
248+
#### OHTTP Usage Example
249+
250+
```kotlin
251+
// Request ads over OHTTP
252+
val ads = client.requestTileAds(placements, MozAdsRequestOptions(ohttp = true))
253+
254+
// Record a click over OHTTP
255+
client.recordClick(ad.callbacks.click, MozAdsCallbackOptions(ohttp = true))
256+
257+
// Record an impression over OHTTP
258+
client.recordImpression(ad.callbacks.impression, MozAdsCallbackOptions(ohttp = true))
259+
```
260+
261+
> **Note:** OHTTP must be configured at the viaduct level before use. When `ohttp` is `true`, the client automatically performs a preflight request to obtain geo-location and user-agent headers, which are injected into the MARS request.
229262
230263
---
231264

0 commit comments

Comments
 (0)