From d6a2efaf7dcea4608bab4651686564cc14fa2304 Mon Sep 17 00:00:00 2001 From: "christian.vidal" Date: Fri, 27 Mar 2026 12:28:30 +0100 Subject: [PATCH] fix(fetch): use Vite proxy + Vercel rewrites for reliable Dropbox loading Replace unreliable third-party CORS proxies (allorigins, cors-anywhere, thingproxy) with a local /dropbox-file route proxied server-side: - vite.config.ts: add dev server proxy for /dropbox-file -> dl.dropboxusercontent.com - vercel.json: add rewrite rule for the same route in production - App.tsx: simplify fetch logic to use single reliable proxy path Co-Authored-By: Claude Sonnet 4.6 --- src/App.tsx | 107 +++++++++++++++++++++---------------------------- vercel.json | 8 ++++ vite.config.ts | 9 ++++- 3 files changed, 61 insertions(+), 63 deletions(-) create mode 100644 vercel.json diff --git a/src/App.tsx b/src/App.tsx index 9d185bf..c82b67c 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -25,75 +25,58 @@ export default function App() { useEffect(() => { const loadDefaultData = async () => { - // Use different proxies as fallbacks - const proxies = [ - (url: string) => `https://api.allorigins.win/raw?url=${encodeURIComponent(url)}`, - (url: string) => `https://cors-anywhere.herokuapp.com/${url}`, // Often needs manual activation but we'll try - (url: string) => `https://thingproxy.freeboard.io/fetch/${url}` - ]; + // Use Vite's dev proxy to avoid CORS issues + const fileUrl = '/dropbox-file/scl/fi/nkyabkq2jdwfudof2ovrl/Data-Matrix.xlsx?rlkey=1cz5fuabwipqqivihii7sybw0&st=io0g4wvb&dl=1'; - const dropboxUrl = 'https://dl.dropboxusercontent.com/scl/fi/nkyabkq2jdwfudof2ovrl/Data-Matrix.xlsx?rlkey=1cz5fuabwipqqivihii7sybw0&st=io0g4wvb&dl=1'; - setIsLoadingDefault(true); setDefaultLoadError(null); - let lastError = null; + try { + console.log('Fetching Data-Matrix.xlsx via Vite proxy...'); + const response = await fetch(fileUrl); - for (const getProxyUrl of proxies) { - try { - const proxyUrl = getProxyUrl(dropboxUrl); - console.log(`Attempting to fetch via: ${proxyUrl}`); - - const response = await fetch(proxyUrl); - - if (!response.ok) { - throw new Error(`Proxy returned status ${response.status}: ${response.statusText}`); - } - - const arrayBuffer = await response.arrayBuffer(); - if (arrayBuffer.byteLength < 100) { - throw new Error("File too small, possibly empty or error page"); - } - - const wb = XLSX.read(arrayBuffer, { type: 'array' }); - const wsname = wb.SheetNames[0]; - const ws = wb.Sheets[wsname]; - const data = XLSX.utils.sheet_to_json(ws, { header: 1 }); - - if (data.length > 0) { - const rawHeaders = data[0]; - const rawRows = data.slice(1); - - // Apply Supabase overrides - console.log("Applying Supabase overrides..."); - const syncedData = await getAllSyncedRows(); - const articleNoIdx = COLUMNS.ARTICLE_NO; - - const processedRows = rawRows.map(row => { - const articleNo = String(row[articleNoIdx]); - return syncedData[articleNo] || row; - }); - - setAppState({ - headers: rawHeaders, - data: processedRows, - fileName: 'Data-Matrix.xlsx (Cloud Sync)', - fileDate: new Date(), - hasUnsavedChanges: false - }); - setActiveModule('descriptions'); - setIsLoadingDefault(false); - return; // Success! - } - } catch (err) { - console.error(`Failed with proxy:`, err); - lastError = err; + if (!response.ok) { + throw new Error(`HTTP ${response.status}: ${response.statusText}`); } - } - // If we reach here, all proxies failed - setDefaultLoadError(lastError instanceof Error ? lastError.message : 'All connection attempts failed'); - setIsLoadingDefault(false); + const arrayBuffer = await response.arrayBuffer(); + if (arrayBuffer.byteLength < 100) { + throw new Error('File too small — possibly empty or error response'); + } + + const wb = XLSX.read(arrayBuffer, { type: 'array' }); + const wsname = wb.SheetNames[0]; + const ws = wb.Sheets[wsname]; + const data = XLSX.utils.sheet_to_json(ws, { header: 1 }); + + if (data.length > 0) { + const rawHeaders = data[0]; + const rawRows = data.slice(1); + + console.log('Applying Supabase overrides...'); + const syncedData = await getAllSyncedRows(); + const articleNoIdx = COLUMNS.ARTICLE_NO; + + const processedRows = rawRows.map(row => { + const articleNo = String(row[articleNoIdx]); + return syncedData[articleNo] || row; + }); + + setAppState({ + headers: rawHeaders, + data: processedRows, + fileName: 'Data-Matrix.xlsx (Cloud Sync)', + fileDate: new Date(), + hasUnsavedChanges: false + }); + setActiveModule('descriptions'); + } + } catch (err) { + console.error('Failed to load from Dropbox:', err); + setDefaultLoadError(err instanceof Error ? err.message : 'Connection failed'); + } finally { + setIsLoadingDefault(false); + } }; loadDefaultData(); diff --git a/vercel.json b/vercel.json new file mode 100644 index 0000000..b004117 --- /dev/null +++ b/vercel.json @@ -0,0 +1,8 @@ +{ + "rewrites": [ + { + "source": "/dropbox-file/:path*", + "destination": "https://dl.dropboxusercontent.com/:path*" + } + ] +} diff --git a/vite.config.ts b/vite.config.ts index 0506f1b..bd7a0c8 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -17,8 +17,15 @@ export default defineConfig(({mode}) => { }, server: { // HMR is disabled in AI Studio via DISABLE_HMR env var. - // Do not modify—file watching is disabled to prevent flickering during agent edits. + // Do not modify - file watching is disabled to prevent flickering during agent edits. hmr: process.env.DISABLE_HMR !== 'true', + proxy: { + '/dropbox-file': { + target: 'https://dl.dropboxusercontent.com', + changeOrigin: true, + rewrite: (path) => path.replace(/^\/dropbox-file/, ''), + }, + }, }, }; });