/** * Centralized CORS configuration for all edge functions * Provides consistent header handling across the application */ // Standard headers that should be allowed across all functions const STANDARD_HEADERS = [ 'authorization', 'x-client-info', 'apikey', 'content-type', 'x-idempotency-key', ]; // Tracing headers for distributed tracing and request tracking const TRACING_HEADERS = [ 'traceparent', 'x-request-id', ]; // All headers combined const ALL_HEADERS = [...STANDARD_HEADERS, ...TRACING_HEADERS]; /** * Basic CORS headers - allows all origins * Use for most edge functions that need public access */ export const corsHeaders = { 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Headers': STANDARD_HEADERS.join(', '), }; /** * Extended CORS headers - includes tracing headers * Use for functions that participate in distributed tracing */ export const corsHeadersWithTracing = { 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Headers': ALL_HEADERS.join(', '), 'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, PATCH, OPTIONS', }; /** * CORS headers with methods - for functions with multiple HTTP verbs */ export const corsHeadersWithMethods = { 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Headers': ALL_HEADERS.join(', '), 'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, PATCH, OPTIONS', }; /** * CORS headers with credentials - for authenticated requests requiring cookies */ export const corsHeadersWithCredentials = { 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Headers': ALL_HEADERS.join(', '), 'Access-Control-Allow-Credentials': 'true', }; /** * Environment-aware CORS configuration * Validates origin against allowlist (production) or localhost (development) */ export const getAllowedOrigin = (requestOrigin: string | null): string | null => { // If no origin header, it's not a CORS request (same-origin or server-to-server) if (!requestOrigin) { return null; } const environment = Deno.env.get('ENVIRONMENT') || 'development'; // Production allowlist - configure via ALLOWED_ORIGINS environment variable const allowedOriginsEnv = Deno.env.get('ALLOWED_ORIGINS') || ''; const allowedOrigins = allowedOriginsEnv.split(',').filter(origin => origin.trim()); // In development, only allow localhost and Replit domains if (environment === 'development') { if ( requestOrigin.includes('localhost') || requestOrigin.includes('127.0.0.1') || requestOrigin.includes('.repl.co') || requestOrigin.includes('.replit.dev') ) { return requestOrigin; } return null; } // In production, only allow specific domains from environment variable if (allowedOrigins.includes(requestOrigin)) { return requestOrigin; } return null; }; /** * Get CORS headers with validated origin * Use for functions requiring strict origin validation (e.g., upload-image) */ export const getCorsHeaders = (allowedOrigin: string | null): Record => { if (!allowedOrigin) { return {}; } return { 'Access-Control-Allow-Origin': allowedOrigin, 'Access-Control-Allow-Headers': ALL_HEADERS.join(', '), 'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, PATCH, OPTIONS', 'Access-Control-Allow-Credentials': 'true', }; }; /** * Handle OPTIONS preflight request * Returns a Response with appropriate CORS headers */ export const handleCorsPreFlight = (corsHeaders: Record): Response => { return new Response(null, { headers: corsHeaders }); };