feat: add Cloudflare edge caching infrastructure for api.worldmonitor.app (#471)

Route web production RPC traffic through api.worldmonitor.app via fetch
interceptor (installWebApiRedirect). Add default Cache-Control headers
(s-maxage=300, stale-while-revalidate=60) on GET 200 responses, with
no-store override for real-time endpoints (vessel snapshot). Update CORS
to allow GET method. Skip Vercel bot middleware for API subdomain using
hostname check (non-spoofable, replacing CF-Ray header approach). Update
desktop cloud fallback to route through api.worldmonitor.app.
This commit is contained in:
Elie Habib
2026-02-27 19:48:49 +04:00
committed by GitHub
parent 7c40542897
commit eabc5166b6
5 changed files with 60 additions and 8 deletions

View File

@@ -142,6 +142,18 @@ export default async function handler(request: Request): Promise<Response> {
mergedHeaders.set(key, value);
}
if (response.status === 200 && request.method === 'GET' && !mergedHeaders.has('Cache-Control')) {
const url = new URL(request.url);
const noStoreEndpoints = new Set([
'/api/maritime/v1/get-vessel-snapshot',
]);
if (noStoreEndpoints.has(url.pathname)) {
mergedHeaders.set('Cache-Control', 'no-store');
} else {
mergedHeaders.set('Cache-Control', 'public, s-maxage=300, stale-while-revalidate=60');
}
}
return new Response(response.body, {
status: response.status,
statusText: response.statusText,

View File

@@ -20,8 +20,13 @@ const SOCIAL_IMAGE_UA =
/Slack-ImgProxy|Slackbot|twitterbot|facebookexternalhit|linkedinbot|telegrambot|whatsapp|discordbot|redditbot/i;
export default function middleware(request: Request) {
const ua = request.headers.get('user-agent') ?? '';
const url = new URL(request.url);
if (url.hostname === 'api.worldmonitor.app') {
return;
}
const ua = request.headers.get('user-agent') ?? '';
const path = url.pathname;
// Allow social preview/image bots on OG image assets (bypasses Vercel Attack Challenge)

View File

@@ -1,8 +1,8 @@
/**
* CORS header generation -- TypeScript port of api/_cors.js.
*
* Identical ALLOWED_ORIGIN_PATTERNS and logic, with methods hardcoded
* to 'POST, OPTIONS' (all sebuf routes are POST).
* Identical ALLOWED_ORIGIN_PATTERNS and logic, with methods set
* to 'GET, POST, OPTIONS' (sebuf routes support GET and POST).
*/
declare const process: { env: Record<string, string | undefined> };
@@ -35,7 +35,7 @@ export function getCorsHeaders(req: Request): Record<string, string> {
const allowOrigin = isAllowedOrigin(origin) ? origin : 'https://worldmonitor.app';
return {
'Access-Control-Allow-Origin': allowOrigin,
'Access-Control-Allow-Methods': 'POST, OPTIONS',
'Access-Control-Allow-Methods': 'GET, POST, OPTIONS',
'Access-Control-Allow-Headers': 'Content-Type, Authorization, X-WorldMonitor-Key',
'Access-Control-Max-Age': '86400',
'Vary': 'Origin',

View File

@@ -142,7 +142,7 @@ window.addEventListener('unhandledrejection', (e) => {
import { debugInjectTestEvents, debugGetCells, getCellCount } from '@/services/geo-convergence';
import { initMetaTags } from '@/services/meta-tags';
import { installRuntimeFetchPatch } from '@/services/runtime';
import { installRuntimeFetchPatch, installWebApiRedirect } from '@/services/runtime';
import { loadDesktopSecrets } from '@/services/runtime-config';
import { initAnalytics, trackApiKeysSnapshot } from '@/services/analytics';
import { applyStoredTheme } from '@/utils/theme-manager';
@@ -163,6 +163,8 @@ initMetaTags();
// In desktop mode, route /api/* calls to the local Tauri sidecar backend.
installRuntimeFetchPatch();
// In web production, route RPC calls through api.worldmonitor.app (Cloudflare edge).
installWebApiRedirect();
loadDesktopSecrets().then(async () => {
await initAnalytics();
trackApiKeysSnapshot();

View File

@@ -1,7 +1,7 @@
const DEFAULT_REMOTE_HOSTS: Record<string, string> = {
tech: 'https://tech.worldmonitor.app',
full: 'https://worldmonitor.app',
world: 'https://worldmonitor.app',
tech: 'https://api.worldmonitor.app',
full: 'https://api.worldmonitor.app',
world: 'https://api.worldmonitor.app',
};
const DEFAULT_LOCAL_API_PORT = 46123;
@@ -130,6 +130,7 @@ const APP_HOSTS = new Set([
'worldmonitor.app',
'www.worldmonitor.app',
'tech.worldmonitor.app',
'api.worldmonitor.app',
'localhost',
'127.0.0.1',
]);
@@ -357,3 +358,35 @@ export function installRuntimeFetchPatch(): void {
(window as unknown as Record<string, unknown>).__wmFetchPatched = true;
}
const WEB_RPC_PATTERN = /^\/api\/[^/]+\/v1\//;
export function installWebApiRedirect(): void {
if (isDesktopRuntime() || typeof window === 'undefined') return;
if ((window as unknown as Record<string, unknown>).__wmWebRedirectPatched) return;
const host = window.location?.hostname ?? '';
const isProduction = host === 'worldmonitor.app' || host === 'www.worldmonitor.app' || host === 'tech.worldmonitor.app';
if (!isProduction) return;
const nativeFetch = window.fetch.bind(window);
const API_BASE = 'https://api.worldmonitor.app';
window.fetch = async (input: RequestInfo | URL, init?: RequestInit): Promise<Response> => {
if (typeof input === 'string' && WEB_RPC_PATTERN.test(input)) {
return nativeFetch(`${API_BASE}${input}`, init);
}
if (input instanceof URL && input.origin === window.location.origin && WEB_RPC_PATTERN.test(input.pathname)) {
return nativeFetch(new URL(`${API_BASE}${input.pathname}${input.search}`), init);
}
if (input instanceof Request) {
const u = new URL(input.url);
if (u.origin === window.location.origin && WEB_RPC_PATTERN.test(u.pathname)) {
return nativeFetch(new Request(`${API_BASE}${u.pathname}${u.search}`, input), init);
}
}
return nativeFetch(input, init);
};
(window as unknown as Record<string, unknown>).__wmWebRedirectPatched = true;
}