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
14 changes: 7 additions & 7 deletions docs/guide/api-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -172,8 +172,8 @@ Click tracking redirect endpoint.
**Example:**

```bash
curl -I "https://edge.example.com/first-party/click?tsurl=https://advertiser.com/landing&campaign=123&tstoken=xyz..."
# → 302 Location: https://advertiser.com/landing?campaign=123&ts-ec=abc123
curl -I "https://edge.example.com/first-party/click?tsurl=https://advertiser.example/landing&campaign=123&tstoken=xyz..."
# → 302 Location: https://advertiser.example/landing?campaign=123&ts-ec=abc123
```

---
Expand All @@ -187,22 +187,22 @@ URL signing endpoint. Returns signed first-party proxy URL for a given target UR
**GET Request:**

```bash
curl "https://edge.example.com/first-party/sign?url=https://external.com/pixel.gif"
curl "https://edge.example.com/first-party/sign?url=https://external.example/pixel.gif"
```

**POST Request:**

```bash
curl -X POST https://edge.example.com/first-party/sign \
-H "Content-Type: application/json" \
-d '{"url":"https://external.com/pixel.gif"}'
-d '{"url":"https://external.example/pixel.gif"}'
```

**Response:**

```json
{
"signed_url": "https://edge.example.com/first-party/proxy?tsurl=https://external.com/pixel.gif&tstoken=abc123..."
"signed_url": "https://edge.example.com/first-party/proxy?tsurl=https://external.example/pixel.gif&tstoken=abc123..."
}
```

Expand All @@ -222,7 +222,7 @@ URL mutation recovery endpoint. Rebuilds signed proxy URL after creative JavaScr

```json
{
"tsclick": "https://edge.example.com/first-party/click?tsurl=https://advertiser.com&campaign=123&tstoken=original...",
"tsclick": "https://edge.example.com/first-party/click?tsurl=https://advertiser.example&campaign=123&tstoken=original...",
"add": {
"utm_source": "banner"
},
Expand All @@ -234,7 +234,7 @@ URL mutation recovery endpoint. Rebuilds signed proxy URL after creative JavaScr

```json
{
"url": "https://edge.example.com/first-party/click?tsurl=https://advertiser.com&campaign=123&utm_source=banner&tstoken=new..."
"url": "https://edge.example.com/first-party/click?tsurl=https://advertiser.example&campaign=123&utm_source=banner&tstoken=new..."
}
```

Expand Down
44 changes: 22 additions & 22 deletions docs/guide/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ Create `trusted-server.toml` in your project root:
[publisher]
domain = "publisher.com"
cookie_domain = ".publisher.com"
origin_url = "https://origin.publisher.com"
origin_url = "https://origin.publisher.example"
proxy_secret = "your-secure-secret-here"

[edge_cookie]
Expand All @@ -36,7 +36,7 @@ at runtime.
```bash
# Format: TRUSTED_SERVER__SECTION__FIELD
export TRUSTED_SERVER__PUBLISHER__DOMAIN=publisher.com
export TRUSTED_SERVER__PUBLISHER__ORIGIN_URL=https://origin.publisher.com
export TRUSTED_SERVER__PUBLISHER__ORIGIN_URL=https://origin.publisher.example
export TRUSTED_SERVER__EDGE_COOKIE__SECRET_KEY=your-secret
```

Expand Down Expand Up @@ -72,7 +72,7 @@ openssl rand -base64 32
[publisher]
domain = "publisher.com"
cookie_domain = ".publisher.com"
origin_url = "https://origin.publisher.com"
origin_url = "https://origin.publisher.example"
proxy_secret = "change-me-to-secure-value"

[edge_cookie]
Expand All @@ -85,7 +85,7 @@ secret_store_id = "01GYYY"

[integrations.prebid]
enabled = true
server_url = "https://prebid-server.com/openrtb2/auction"
server_url = "https://prebid-server.example/openrtb2/auction"
timeout_ms = 1200
bidders = ["kargo", "appnexus", "openx"]
client_side_bidders = ["rubicon"]
Expand Down Expand Up @@ -166,7 +166,7 @@ Core publisher settings for domain, origin, and proxy configuration.
[publisher]
domain = "publisher.com"
cookie_domain = ".publisher.com" # Includes subdomains
origin_url = "https://origin.publisher.com"
origin_url = "https://origin.publisher.example"
proxy_secret = "change-me-to-secure-random-value"
```

Expand All @@ -175,7 +175,7 @@ proxy_secret = "change-me-to-secure-random-value"
```bash
TRUSTED_SERVER__PUBLISHER__DOMAIN=publisher.com
TRUSTED_SERVER__PUBLISHER__COOKIE_DOMAIN=.publisher.com
TRUSTED_SERVER__PUBLISHER__ORIGIN_URL=https://origin.publisher.com
TRUSTED_SERVER__PUBLISHER__ORIGIN_URL=https://origin.publisher.example
TRUSTED_SERVER__PUBLISHER__PROXY_SECRET=your-secret-here
```

Expand All @@ -194,7 +194,7 @@ TRUSTED_SERVER__PUBLISHER__PROXY_SECRET=your-secret-here

- ✅ `publisher.com`
- ✅ `www.publisher.com`
- ❌ `https://publisher.com`
- ❌ `https://publisher.example`
- ❌ `publisher.com/path`

#### `cookie_domain`
Expand Down Expand Up @@ -225,10 +225,10 @@ TRUSTED_SERVER__PUBLISHER__PROXY_SECRET=your-secret-here

**Format**: Full URL with protocol

- ✅ `https://origin.publisher.com`
- ✅ `https://origin.publisher.com:8080`
- ✅ `https://origin.publisher.example`
- ✅ `https://origin.publisher.example:8080`
- ✅ `http://192.168.1.1:9000`
- ❌ `origin.publisher.com` (missing protocol)
- ❌ `origin.publisher.example` (missing protocol)

**Port Handling**: Includes port if non-standard (not 80/443).

Expand Down Expand Up @@ -564,7 +564,7 @@ Matches:
- ✅ `assets.cdn.example.com`
- ✅ `images.cdn.example.com`
- ✅ `cdn.example.com` (base domain)
- ❌ `cdn.example.com.evil.com` (different domain)
- ❌ `cdn.example.com.evil.example` (different domain)

**Exact Patterns** (no `*`):

Expand All @@ -576,14 +576,14 @@ Matches:

- ✅ `api.example.com`
- ❌ `www.api.example.com`
- ❌ `api.example.com.evil.com`
- ❌ `api.example.com.evil.example`

### Use Cases

**Trusted Partners**:

```toml
exclude_domains = ["*.approved-cdn.com"]
exclude_domains = ["*.approved-cdn.example"]
```

**First-Party Resources**:
Expand Down Expand Up @@ -621,7 +621,7 @@ Controls first-party proxy security settings.
```toml
[proxy]
allowed_domains = [
"tracker.com", # Exact match
"tracker.example", # Exact match
"*.adserver.com", # Wildcard: adserver.com and all subdomains
"*.trusted-cdn.net",
]
Expand All @@ -631,14 +631,14 @@ allowed_domains = [

```bash
# JSON array
TRUSTED_SERVER__PROXY__ALLOWED_DOMAINS='["tracker.com","*.adserver.com"]'
TRUSTED_SERVER__PROXY__ALLOWED_DOMAINS='["tracker.example","*.adserver.com"]'

# Indexed
TRUSTED_SERVER__PROXY__ALLOWED_DOMAINS__0="tracker.com"
TRUSTED_SERVER__PROXY__ALLOWED_DOMAINS__0="tracker.example"
TRUSTED_SERVER__PROXY__ALLOWED_DOMAINS__1="*.adserver.com"

# Comma-separated
TRUSTED_SERVER__PROXY__ALLOWED_DOMAINS="tracker.com,*.adserver.com"
TRUSTED_SERVER__PROXY__ALLOWED_DOMAINS="tracker.example,*.adserver.com"
```

### Field Details
Expand All @@ -653,10 +653,10 @@ TRUSTED_SERVER__PROXY__ALLOWED_DOMAINS="tracker.com,*.adserver.com"

**Pattern Matching**:

| Pattern | Matches | Does not match |
| --------------- | --------------------------------------------------- | ------------------ |
| `tracker.com` | `tracker.com` | `sub.tracker.com` |
| `*.tracker.com` | `tracker.com`, `sub.tracker.com`, `a.b.tracker.com` | `evil-tracker.com` |
| Pattern | Matches | Does not match |
| ------------------- | --------------------------------------------------------------- | ---------------------- |
| `tracker.example` | `tracker.example` | `sub.tracker.example` |
| `*.tracker.example` | `tracker.example`, `sub.tracker.example`, `a.b.tracker.example` | `evil-tracker.example` |

- `"example.com"` — exact match only.
- `"*.example.com"` — matches the base domain and any subdomain at any depth.
Expand Down Expand Up @@ -961,7 +961,7 @@ proxy_secret = "dev-secret"

```bash
# .env.staging
TRUSTED_SERVER__PUBLISHER__ORIGIN_URL=https://staging.publisher.com
TRUSTED_SERVER__PUBLISHER__ORIGIN_URL=https://staging.publisher.example
TRUSTED_SERVER__PUBLISHER__PROXY_SECRET=$(cat /run/secrets/proxy_secret_staging)
```

Expand Down
63 changes: 32 additions & 31 deletions docs/guide/creative-processing.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ Creative processing transforms third-party ad creatives by rewriting URLs to go
```
┌──────────────────────────────────────────────────────┐
│ Original Creative HTML │
│ <img src="https://tracker.com/pixel.gif"> │
│ <iframe src="https://cdn.com/ad.html"> │
│ <style> .bg { background: url(cdn.com/bg.jpg); } │
│ <img src="https://tracker.example/pixel.gif"> │
│ <iframe src="https://cdn.example/ad.html"> │
│ <style> .bg { background: url(cdn.example/bg.jpg); } │
└──────────────────────────────────────────────────────┘
┌──────────────────────────────────────────────────────┐
Expand Down Expand Up @@ -166,11 +166,11 @@ When `with_streaming()` is enabled in `ProxyRequestConfig`, HTML/CSS processing

```html
<!-- Original -->
<iframe src="https://advertiser.com/creative.html"></iframe>
<iframe src="https://advertiser.example/creative.html"></iframe>

<!-- Rewritten -->
<iframe
src="/first-party/proxy?tsurl=https://advertiser.com/creative.html&tstoken=sig"
src="/first-party/proxy?tsurl=https://advertiser.example/creative.html&tstoken=sig"
></iframe>
```

Expand Down Expand Up @@ -226,11 +226,11 @@ If the iframe content itself contains HTML, it will be processed recursively. Ea

```html
<!-- Original -->
<a href="https://advertiser.com/product?id=123">Buy Now</a>
<a href="https://advertiser.example/product?id=123">Buy Now</a>

<!-- Rewritten -->
<a
href="/first-party/click?tsurl=https://advertiser.com/product&id=123&tstoken=sig"
href="/first-party/click?tsurl=https://advertiser.example/product&id=123&tstoken=sig"
>Buy Now</a
>
```
Expand Down Expand Up @@ -435,18 +435,18 @@ Descriptors are preserved exactly as written:
<!-- Original -->
<img
srcset="
https://cdn.com/small.jpg 480w,
https://cdn.com/medium.jpg 800w,
https://cdn.com/large.jpg 1200w
https://cdn.example/small.jpg 480w,
https://cdn.example/medium.jpg 800w,
https://cdn.example/large.jpg 1200w
"
/>

<!-- Rewritten -->
<img
srcset="
/first-party/proxy?tsurl=https://cdn.com/small.jpg&tstoken=sig1 480w,
/first-party/proxy?tsurl=https://cdn.com/medium.jpg&tstoken=sig2 800w,
/first-party/proxy?tsurl=https://cdn.com/large.jpg&tstoken=sig3 1200w
/first-party/proxy?tsurl=https://cdn.example/small.jpg&tstoken=sig1 480w,
/first-party/proxy?tsurl=https://cdn.example/medium.jpg&tstoken=sig2 800w,
/first-party/proxy?tsurl=https://cdn.example/large.jpg&tstoken=sig3 1200w
"
/>
```
Expand All @@ -457,13 +457,13 @@ Srcset can mix absolute and relative URLs:

```html
<!-- Original -->
<img srcset="/local/small.jpg 1x, https://cdn.com/large.jpg 2x" />
<img srcset="/local/small.jpg 1x, https://cdn.example/large.jpg 2x" />

<!-- Rewritten (only absolute URL) -->
<img
srcset="
/local/small.jpg 1x,
/first-party/proxy?tsurl=https://cdn.com/large.jpg&tstoken=sig 2x
/local/small.jpg 1x,
/first-party/proxy?tsurl=https://cdn.example/large.jpg&tstoken=sig 2x
"
/>
```
Expand Down Expand Up @@ -496,23 +496,23 @@ Common properties with `url()` values:

```css
/* Background images */
background: url(https://cdn.com/bg.jpg);
background-image: url(https://cdn.com/pattern.png);
background: url(https://cdn.example/bg.jpg);
background-image: url(https://cdn.example/pattern.png);

/* Borders */
border-image: url(https://cdn.com/border.svg);
border-image: url(https://cdn.example/border.svg);

/* List styles */
list-style-image: url(https://cdn.com/bullet.png);
list-style-image: url(https://cdn.example/bullet.png);

/* Cursors */
cursor: url(https://cdn.com/cursor.cur), pointer;
cursor: url(https://cdn.example/cursor.cur), pointer;

/* Masks */
mask-image: url(https://cdn.com/mask.svg);
mask-image: url(https://cdn.example/mask.svg);

/* Filters */
filter: url(https://cdn.com/filter.svg#blur);
filter: url(https://cdn.example/filter.svg#blur);
```

**All `url()` occurrences are rewritten** regardless of property.
Expand All @@ -525,15 +525,16 @@ Properties can have multiple `url()` values:
/* Original */
.element {
background:
url(https://cdn.com/top.png) top,
url(https://cdn.com/bottom.png) bottom;
url(https://cdn.example/top.png) top,
url(https://cdn.example/bottom.png) bottom;
}

/* Rewritten */
.element {
background:
url(/first-party/proxy?tsurl=https://cdn.com/top.png&tstoken=sig1) top,
url(/first-party/proxy?tsurl=https://cdn.com/bottom.png&tstoken=sig2) bottom;
url(/first-party/proxy?tsurl=https://cdn.example/top.png&tstoken=sig1) top,
url(/first-party/proxy?tsurl=https://cdn.example/bottom.png&tstoken=sig2)
bottom;
}
```

Expand Down Expand Up @@ -574,7 +575,7 @@ Matches:
✅ assets.cdn.example.com
✅ images.cdn.example.com
❌ cdn.example.com (no subdomain)
❌ cdn.example.com.evil.com (different domain)
❌ cdn.example.com.evil.example (different domain)
```

**Exact Patterns**: No `*` requires exact host match
Expand All @@ -584,15 +585,15 @@ Pattern: api.example.com
Matches:
✅ api.example.com
❌ www.api.example.com
❌ api.example.com.evil.com
❌ api.example.com.evil.example
```

### Use Cases

**Trusted Partners**:

```toml
exclude_domains = ["*.trusted-cdn.com"]
exclude_domains = ["*.trusted-cdn.example"]
```

Skip rewriting for partners already providing first-party scripts.
Expand Down Expand Up @@ -834,7 +835,7 @@ log::debug!("creative: skipped non-network scheme {}", url);
3. Compare output

```rust
let original = "<img src=\"https://tracker.com/pixel.gif\">";
let original = "<img src=\"https://tracker.example/pixel.gif\">";
let rewritten = rewrite_creative_html(&settings, original);
assert!(rewritten.contains("/first-party/proxy"));
```
Expand Down
4 changes: 2 additions & 2 deletions docs/guide/error-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ Missing required field: publisher.domain
```toml
[publisher]
domain = "your-publisher-domain.com"
origin_url = "https://origin.your-publisher-domain.com"
origin_url = "https://origin.your-publisher-domain.example"
proxy_secret = "change-me-to-random-string"
```

Expand Down Expand Up @@ -203,7 +203,7 @@ Invalid tstoken signature

```bash
# Test URL signing
curl "https://edge.example.com/first-party/sign?url=https://external.com/pixel.gif"
curl "https://edge.example.com/first-party/sign?url=https://external.example/pixel.gif"
```

---
Expand Down
Loading
Loading