mirror of
https://github.com/pacnpal/thrilltrack-explorer.git
synced 2025-12-20 08:31:12 -05:00
Connect to Lovable Cloud
Improve CORS handling and error logging to fix moderation edge cases: - Add x-idempotency-key to allowed CORS headers and expose explicit POST methods - Extend CORS headers to include Access-Control-Allow-Methods - Update edge function tracing and client error handling to better detect and log CORS/network issues - Enhance error handling utilities to surface CORS-related failures and provide clearer user messages
This commit is contained in:
@@ -10,6 +10,7 @@ import { trackRequest } from './requestTracking';
|
||||
import { getErrorMessage } from './errorHandler';
|
||||
import { withRetry, isRetryableError, type RetryOptions } from './retryHelpers';
|
||||
import { breadcrumb } from './errorBreadcrumbs';
|
||||
import { logger } from './logger';
|
||||
|
||||
/**
|
||||
* Invoke a Supabase edge function with request tracking
|
||||
@@ -149,9 +150,31 @@ export async function invokeWithTracking<T = any>(
|
||||
}
|
||||
|
||||
const errorMessage = getErrorMessage(error);
|
||||
|
||||
// Detect CORS errors specifically
|
||||
const isCorsError = errorMessage.toLowerCase().includes('cors') ||
|
||||
errorMessage.toLowerCase().includes('cross-origin') ||
|
||||
errorMessage.toLowerCase().includes('failed to send') ||
|
||||
(error instanceof TypeError && errorMessage.toLowerCase().includes('failed to fetch'));
|
||||
|
||||
// Enhanced error logging
|
||||
logger.error('[EdgeFunctionTracking] Edge function invocation failed', {
|
||||
functionName,
|
||||
error: errorMessage,
|
||||
errorType: isCorsError ? 'CORS/Network' : (error as any)?.name || 'Unknown',
|
||||
attempts: attemptCount,
|
||||
isCorsError,
|
||||
debugHint: isCorsError ? 'Browser blocked request - verify CORS headers allow X-Idempotency-Key or check network connectivity' : undefined,
|
||||
status: (error as any)?.status,
|
||||
});
|
||||
|
||||
return {
|
||||
data: null,
|
||||
error: { message: errorMessage, status: (error as any)?.status },
|
||||
error: {
|
||||
message: errorMessage,
|
||||
status: (error as any)?.status,
|
||||
isCorsError,
|
||||
},
|
||||
requestId: 'unknown',
|
||||
duration: 0,
|
||||
attempts: attemptCount,
|
||||
|
||||
@@ -38,12 +38,24 @@ export function isSupabaseConnectionError(error: unknown): boolean {
|
||||
|
||||
// Database connection errors (08xxx codes)
|
||||
if (supabaseError.code?.startsWith('08')) return true;
|
||||
|
||||
// Check message for CORS and connectivity keywords
|
||||
const message = supabaseError.message?.toLowerCase() || '';
|
||||
if (message.includes('cors') ||
|
||||
message.includes('cross-origin') ||
|
||||
message.includes('failed to send')) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Network fetch errors
|
||||
if (error instanceof TypeError) {
|
||||
const message = error.message.toLowerCase();
|
||||
if (message.includes('fetch') || message.includes('network') || message.includes('failed to fetch')) {
|
||||
if (message.includes('fetch') ||
|
||||
message.includes('network') ||
|
||||
message.includes('failed to fetch') ||
|
||||
message.includes('cors') ||
|
||||
message.includes('cross-origin')) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -61,7 +73,15 @@ export const handleError = (
|
||||
|
||||
// Check if this is a connection error and dispatch event
|
||||
if (isSupabaseConnectionError(error)) {
|
||||
window.dispatchEvent(new CustomEvent('api-connectivity-down'));
|
||||
const errorMsg = getErrorMessage(error).toLowerCase();
|
||||
const isCors = errorMsg.includes('cors') || errorMsg.includes('cross-origin');
|
||||
|
||||
window.dispatchEvent(new CustomEvent('api-connectivity-down', {
|
||||
detail: {
|
||||
isCorsError: isCors,
|
||||
error: errorMsg,
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
// Enhanced error message and stack extraction
|
||||
@@ -132,6 +152,9 @@ export const handleError = (
|
||||
}
|
||||
|
||||
// Log to console/monitoring with enhanced debugging
|
||||
const isCorsError = errorMessage.toLowerCase().includes('cors') ||
|
||||
errorMessage.toLowerCase().includes('cross-origin') ||
|
||||
errorMessage.toLowerCase().includes('failed to send');
|
||||
|
||||
logger.error('Error occurred', {
|
||||
...context,
|
||||
@@ -144,6 +167,8 @@ export const handleError = (
|
||||
hasStack: !!stack,
|
||||
isSyntheticStack: !!(error && typeof error === 'object' && !(error instanceof Error) && stack),
|
||||
supabaseError: supabaseErrorDetails,
|
||||
isCorsError,
|
||||
debugHint: isCorsError ? 'Browser blocked request - check CORS headers or network connectivity' : undefined,
|
||||
});
|
||||
|
||||
// Additional debug logging when stack is missing
|
||||
|
||||
@@ -9,6 +9,7 @@ const STANDARD_HEADERS = [
|
||||
'x-client-info',
|
||||
'apikey',
|
||||
'content-type',
|
||||
'x-idempotency-key',
|
||||
];
|
||||
|
||||
// Tracing headers for distributed tracing and request tracking
|
||||
@@ -36,6 +37,7 @@ export const corsHeaders = {
|
||||
export const corsHeadersWithTracing = {
|
||||
'Access-Control-Allow-Origin': '*',
|
||||
'Access-Control-Allow-Headers': ALL_HEADERS.join(', '),
|
||||
'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, PATCH, OPTIONS',
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user