| |
| |
| |
| |
| |
| |
|
|
| const PRODUCTION_PATTERNS: RegExp[] = [ |
| /^https:\/\/(.*\.)?worldmonitor\.app$/, |
| |
| |
| |
| |
| /^https:\/\/worldmonitor-[a-z0-9-]+-eliewm\.vercel\.app$/, |
| /^https?:\/\/tauri\.localhost(:\d+)?$/, |
| /^https?:\/\/[a-z0-9-]+\.tauri\.localhost(:\d+)?$/i, |
| /^tauri:\/\/localhost$/, |
| /^asset:\/\/localhost$/, |
| ]; |
|
|
| const DEV_PATTERNS: RegExp[] = [ |
| /^https?:\/\/localhost(:\d+)?$/, |
| /^https?:\/\/127\.0\.0\.1(:\d+)?$/, |
| ]; |
|
|
| const ALLOWED_ORIGIN_PATTERNS: RegExp[] = |
| process.env.NODE_ENV === 'production' |
| ? PRODUCTION_PATTERNS |
| : [...PRODUCTION_PATTERNS, ...DEV_PATTERNS]; |
|
|
| const ALLOWED_HEADERS = [ |
| 'Content-Type', |
| 'Authorization', |
| 'X-WorldMonitor-Key', |
| 'X-Api-Key', |
| 'X-Widget-Key', |
| 'X-Pro-Key', |
| 'X-WorldMonitor-Desktop-Timestamp', |
| 'X-WorldMonitor-Desktop-Signature', |
| 'Idempotency-Key', |
| 'Mcp-Session-Id', |
| 'MCP-Protocol-Version', |
| 'Last-Event-ID', |
| ].join(', '); |
|
|
| const EXPOSED_HEADERS = [ |
| 'Mcp-Session-Id', |
| 'WWW-Authenticate', |
| 'Retry-After', |
| 'Idempotency-Key', |
| 'Idempotent-Replayed', |
| 'Location', |
| |
| |
| 'X-Billing-Verification', |
| 'X-RateLimit-Limit', |
| 'X-RateLimit-Remaining', |
| 'X-RateLimit-Reset', |
| 'X-WorldMonitor-Bbox', |
| 'X-WorldMonitor-Bbox-Missing', |
| 'X-WorldMonitor-Bbox-Invalid', |
| 'X-Military-Bbox', |
| ].join(', '); |
|
|
| export function isAllowedOrigin(origin: string): boolean { |
| return Boolean(origin) && ALLOWED_ORIGIN_PATTERNS.some((pattern) => pattern.test(origin)); |
| } |
|
|
| export function getCorsHeaders(req: Request): Record<string, string> { |
| const origin = req.headers.get('origin') || ''; |
| const allowOrigin = isAllowedOrigin(origin) ? origin : 'https://worldmonitor.app'; |
| return { |
| 'Access-Control-Allow-Origin': allowOrigin, |
| 'Access-Control-Allow-Credentials': 'true', |
| 'Access-Control-Allow-Methods': 'GET, POST, OPTIONS', |
| 'Access-Control-Allow-Headers': ALLOWED_HEADERS, |
| 'Access-Control-Expose-Headers': EXPOSED_HEADERS, |
| 'Access-Control-Max-Age': '3600', |
| 'Vary': 'Origin', |
| }; |
| } |
|
|
| export function isDisallowedOrigin(req: Request): boolean { |
| const origin = req.headers.get('origin'); |
| if (!origin) return false; |
| return !isAllowedOrigin(origin); |
| } |
|
|