extension-install-cors.ts
1 const DEFAULT_ALLOWED_ORIGINS = [ 2 'https://swarmclaw.ai', 3 'https://www.swarmclaw.ai', 4 'http://localhost:3000', 5 'http://127.0.0.1:3000', 6 ] 7 8 function parseAllowedOrigins(raw: string | undefined): string[] { 9 if (!raw) return DEFAULT_ALLOWED_ORIGINS 10 const parsed = raw 11 .split(',') 12 .map((entry) => entry.trim()) 13 .filter(Boolean) 14 return parsed.length > 0 ? parsed : DEFAULT_ALLOWED_ORIGINS 15 } 16 17 function normalizeOrigin(raw: string | null | undefined): string { 18 if (!raw) return '' 19 try { 20 return new URL(raw).origin 21 } catch { 22 return '' 23 } 24 } 25 26 export function resolveExtensionInstallCorsOrigin(rawOrigin: string | null | undefined): string | null { 27 const origin = normalizeOrigin(rawOrigin) 28 if (!origin) return null 29 const allowed = parseAllowedOrigins(process.env.SWARMCLAW_EXTENSION_INSTALL_ORIGINS) 30 return allowed.includes(origin) ? origin : null 31 } 32 33 export function buildExtensionInstallCorsHeaders(origin: string | null): HeadersInit { 34 const headers = new Headers() 35 headers.set('Vary', 'Origin') 36 if (!origin) return headers 37 headers.set('Access-Control-Allow-Origin', origin) 38 headers.set('Access-Control-Allow-Headers', 'Content-Type, X-Access-Key') 39 headers.set('Access-Control-Allow-Methods', 'POST, OPTIONS') 40 headers.set('Access-Control-Max-Age', '600') 41 return headers 42 } 43 44 export function isExtensionInstallCorsPath(pathname: string): boolean { 45 return pathname === '/api/extensions/install' 46 }