fix(gateway): gate CDN-Cache-Control on trusted origin#2496
Conversation
… bypass No-origin server-side requests (external scrapers) no longer receive a CDN-Cache-Control header, so Vercel CDN never caches their responses. Every request without a trusted origin must reach the edge function, ensuring validateApiKey() always runs and returns 401 for unauthenticated callers. Trusted origins (worldmonitor.app, Vercel previews, Tauri) are unchanged — CDN caching behaviour and hit rates for the app itself are unaffected.
|
Preview deployment for your docs. Learn more about Mintlify Previews.
|
|
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
Greptile SummaryThis PR closes a CDN cache-bypass path by gating the Key changes:
Confidence Score: 5/5Safe to merge — the fix is logically correct, has no impact on existing trusted-origin callers, and the only finding is a P2 suggestion to add a regression test. The logic is sound: isAllowedOrigin('') correctly returns false (guarded by Boolean(origin)), so no-origin requests always receive cdnCache = null and never emit CDN-Cache-Control. Trusted-origin behavior is unchanged. The single comment is a non-blocking P2 test-coverage suggestion. No files require special attention; server/gateway.ts holds the core change and reads correctly. Important Files Changed
Sequence DiagramsequenceDiagram
participant B as Browser (trusted origin)
participant S as Scraper (no origin)
participant CDN as Vercel CDN
participant EF as Edge Function
participant AK as validateApiKey()
note over B,AK: BEFORE fix
B->>CDN: GET /api/… Origin: worldmonitor.app
CDN->>EF: cache miss → invoke
EF->>AK: check key
AK-->>EF: ✓ allowed
EF-->>CDN: 200 + CDN-Cache-Control (cached under origin=worldmonitor.app)
CDN-->>B: 200
S->>CDN: GET /api/… (no Origin, no key)
CDN->>EF: cache miss → invoke
EF->>AK: check key (public route)
AK-->>EF: ✓ allowed
EF-->>CDN: 200 + CDN-Cache-Control (cached under origin=empty)
CDN-->>S: 200 ← cached for all future no-origin callers!
S->>CDN: GET /api/… (no Origin, no key) second request
CDN-->>S: 200 (served from cache, edge function never invoked)
note over B,AK: AFTER fix
B->>CDN: GET /api/… Origin: worldmonitor.app
CDN->>EF: cache miss → invoke
EF-->>CDN: 200 + CDN-Cache-Control (still cached for trusted origins)
CDN-->>B: 200
S->>CDN: GET /api/… (no Origin, no key)
CDN->>EF: always a miss — no CDN-Cache-Control ever set for no-origin
EF->>AK: check key
AK-->>EF: ✗ 401
EF-->>S: 401 (never cached)
Reviews (1): Last reviewed commit: "fix(gateway): gate CDN-Cache-Control on ..." | Re-trigger Greptile |
|
Thanks for the review. Addressing each point: 1. Cache-Control with s-maxage
2. Empty string short-circuit Confirmed correct. 3. Tauri Origin header Tauri's webview (WKWebView on macOS/Linux, WebView2 on Windows) is a full browser engine and does send
The only Tauri path that produces no-Origin requests is the sidecar's Node.js |
Why
External projects have been discovered calling WorldMonitor API endpoints server-side (no
Originheader, no key). The Vercel CDN servess-maxagecached responses without re-invoking the edge function, meaning a 200 cached by a trusted-origin browser request could potentially be served back to an unauthenticated no-origin caller, bypassingvalidateApiKey().What changed
server/cors.ts— exportsisAllowedOriginso the gateway can reuse the same trusted-origin logic.server/gateway.ts— gatesCDN-Cache-Controlon whether the request came from a trusted origin:No-origin requests now receive only
Cache-Control(browser/client hint) and neverCDN-Cache-Control, so Vercel CDN never stores their responses. Every no-origin request must reach the edge function, wherevalidateApiKey()returns 401.Impact
Future
When the developer API program ships, the condition can be extended to
isAllowedOrigin(reqOrigin) || hasValidDevKeyso external developers with PRO keys also benefit from CDN caching.