Skip to content

Commit f2e471c

Browse files
committed
feat(test): add cache-demo fixture for CacheOverride API
Adds a comprehensive demo fixture that showcases the CacheOverride API with real caching scenarios using httpbin as a backend. Routes: - /cache-demo/long - Long cache (1 hour TTL) - /cache-demo/short - Short cache (10 seconds TTL) - /cache-demo/no-cache - No caching (pass mode) - /cache-demo/custom - Custom cache key based on User-Agent - /cache-demo/ - Info page The demo uses httpbin.org/uuid to demonstrate cache hits vs misses, making it easy to verify caching behavior in real deployments. Signed-off-by: Lars Trieloff <lars@trieloff.net>
1 parent 2b13337 commit f2e471c

File tree

3 files changed

+228
-0
lines changed

3 files changed

+228
-0
lines changed

test/fixtures/cache-demo/README.md

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
# CacheOverride API Demo
2+
3+
This fixture demonstrates the cross-platform `CacheOverride` API for cache control on both Fastly Compute and Cloudflare Workers.
4+
5+
## Routes
6+
7+
### Info Page
8+
- **URL**: `/cache-demo/`
9+
- **Description**: Returns API information and available routes
10+
11+
### Long Cache
12+
- **URL**: `/cache-demo/long`
13+
- **Cache**: 1 hour TTL
14+
- **Surrogate Key**: `cache-demo long-cache`
15+
- **Use Case**: Static content that rarely changes
16+
17+
### Short Cache
18+
- **URL**: `/cache-demo/short`
19+
- **Cache**: 10 seconds TTL
20+
- **Surrogate Key**: `cache-demo short-cache`
21+
- **Use Case**: Frequently updated content
22+
23+
### No Cache
24+
- **URL**: `/cache-demo/no-cache`
25+
- **Cache**: Disabled (pass mode)
26+
- **Use Case**: Always-fresh, dynamic content
27+
28+
### Custom Cache Key
29+
- **URL**: `/cache-demo/custom`
30+
- **Cache**: 5 minutes TTL with custom cache key based on User-Agent
31+
- **Surrogate Key**: `cache-demo custom-key`
32+
- **Use Case**: Per-client caching strategies
33+
34+
## Testing
35+
36+
Each route fetches a UUID from `httpbin.org/uuid` and returns:
37+
- The UUID (should be the same for cached responses)
38+
- Timestamp
39+
- Runtime information
40+
- Cache configuration
41+
- Response headers
42+
43+
To test caching:
44+
1. Call `/cache-demo/short` multiple times quickly - should return the same UUID
45+
2. Wait 10 seconds and call again - should return a new UUID
46+
3. Call `/cache-demo/no-cache` - should always return a new UUID
47+
48+
## Backend
49+
50+
Uses `httpbin.org` as a test backend:
51+
- **Endpoint**: `/uuid` - Returns a unique identifier
52+
- **Purpose**: Easy way to verify cache hits (same UUID) vs cache misses (new UUID)
53+
54+
## Example Response
55+
56+
```json
57+
{
58+
"description": "Short cache (10 seconds)",
59+
"timestamp": "2025-11-19T22:50:00.000Z",
60+
"runtime": "cloudflare-workers",
61+
"backend": {
62+
"url": "https://httpbin.org/uuid",
63+
"status": 200,
64+
"data": {
65+
"uuid": "12345678-1234-1234-1234-123456789abc"
66+
}
67+
},
68+
"cache": {
69+
"mode": "override",
70+
"options": {
71+
"ttl": 10,
72+
"surrogateKey": "cache-demo short-cache"
73+
}
74+
},
75+
"headers": {
76+
"cache-control": "public, max-age=10",
77+
"age": "5",
78+
"x-cache": "HIT"
79+
}
80+
}
81+
```
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{
2+
"name": "cache-demo",
3+
"version": "1.0.0",
4+
"description": "CacheOverride API Demo",
5+
"private": true,
6+
"license": "Apache-2.0",
7+
"main": "src/index.js",
8+
"type": "module",
9+
"wsk": {
10+
"name": "cache-demo",
11+
"webExport": true,
12+
"package": {
13+
"name": "helix-services"
14+
}
15+
},
16+
"devDependencies": {
17+
"@adobe/fetch": "^4.1.8"
18+
}
19+
}
Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
/*
2+
* Copyright 2025 Adobe. All rights reserved.
3+
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
4+
* you may not use this file except in compliance with the License. You may obtain a copy
5+
* of the License at http://www.apache.org/licenses/LICENSE-2.0
6+
*
7+
* Unless required by applicable law or agreed to in writing, software distributed under
8+
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9+
* OF ANY KIND, either express or implied. See the License for the specific language
10+
* governing permissions and limitations under the License.
11+
*/
12+
import { Response, fetch, CacheOverride } from '@adobe/fetch';
13+
14+
/**
15+
* Cache Demo Action
16+
* Demonstrates cross-platform CacheOverride API usage with httpbin backend
17+
*
18+
* Routes:
19+
* - /cache-demo/long - Long cache (1 hour)
20+
* - /cache-demo/short - Short cache (10 seconds)
21+
* - /cache-demo/no-cache - No caching (pass mode)
22+
* - /cache-demo/custom - Custom cache key example
23+
* - /cache-demo/ - Info page
24+
*/
25+
export async function main(req, context) {
26+
const url = new URL(req.url);
27+
const path = url.pathname;
28+
29+
// Backend base URL
30+
const backendBase = 'https://httpbin.org';
31+
32+
let cacheOverride;
33+
let description;
34+
let backendPath = '/uuid'; // Default: returns a unique ID
35+
36+
if (path.includes('/long')) {
37+
// Long cache: 1 hour TTL
38+
cacheOverride = new CacheOverride('override', {
39+
ttl: 3600,
40+
surrogateKey: 'cache-demo long-cache',
41+
});
42+
description = 'Long cache (1 hour)';
43+
} else if (path.includes('/short')) {
44+
// Short cache: 10 seconds TTL
45+
cacheOverride = new CacheOverride('override', {
46+
ttl: 10,
47+
surrogateKey: 'cache-demo short-cache',
48+
});
49+
description = 'Short cache (10 seconds)';
50+
} else if (path.includes('/no-cache')) {
51+
// No caching
52+
cacheOverride = new CacheOverride('pass');
53+
description = 'No caching (always fresh)';
54+
} else if (path.includes('/custom')) {
55+
// Custom cache key example
56+
const userAgent = req.headers.get('user-agent') || 'unknown';
57+
const cacheKey = `cache-demo-${userAgent.substring(0, 20)}`;
58+
cacheOverride = new CacheOverride({
59+
ttl: 300,
60+
cacheKey,
61+
surrogateKey: 'cache-demo custom-key',
62+
});
63+
description = `Custom cache key: ${cacheKey}`;
64+
} else {
65+
// Info page
66+
return new Response(
67+
JSON.stringify({
68+
name: 'CacheOverride API Demo',
69+
version: '1.0.0',
70+
runtime: context?.runtime?.name || 'unknown',
71+
routes: {
72+
'/cache-demo/long': 'Long cache (1 hour TTL)',
73+
'/cache-demo/short': 'Short cache (10 seconds TTL)',
74+
'/cache-demo/no-cache': 'No caching (pass mode)',
75+
'/cache-demo/custom': 'Custom cache key (5 minutes TTL)',
76+
},
77+
documentation: 'https://github.com/adobe/helix-deploy-plugin-edge',
78+
}, null, 2),
79+
{
80+
status: 200,
81+
headers: {
82+
'Content-Type': 'application/json',
83+
'X-Cache-Demo': 'info',
84+
},
85+
},
86+
);
87+
}
88+
89+
// Fetch from backend with cache override
90+
const backendUrl = `${backendBase}${backendPath}`;
91+
const backendResponse = await fetch(backendUrl, {
92+
backend: 'httpbin.org',
93+
cacheOverride,
94+
});
95+
96+
const backendData = await backendResponse.json();
97+
const timestamp = new Date().toISOString();
98+
99+
// Build response
100+
const responseData = {
101+
description,
102+
timestamp,
103+
runtime: context?.runtime?.name || 'unknown',
104+
backend: {
105+
url: backendUrl,
106+
status: backendResponse.status,
107+
data: backendData,
108+
},
109+
cache: {
110+
mode: cacheOverride.mode,
111+
options: cacheOverride.options,
112+
},
113+
headers: {
114+
'cache-control': backendResponse.headers.get('cache-control'),
115+
'age': backendResponse.headers.get('age'),
116+
'x-cache': backendResponse.headers.get('x-cache'),
117+
},
118+
};
119+
120+
return new Response(JSON.stringify(responseData, null, 2), {
121+
status: 200,
122+
headers: {
123+
'Content-Type': 'application/json',
124+
'X-Cache-Demo': description,
125+
'X-Timestamp': timestamp,
126+
},
127+
});
128+
}

0 commit comments

Comments
 (0)