From 7344d5a2b11e2bbebf6a9a9000cb4c89a1124db9 Mon Sep 17 00:00:00 2001 From: Deep Koluguri Date: Wed, 24 Jun 2026 19:17:43 -0400 Subject: [PATCH] fix: static files before routes, fix CSP for assets and Cloudflare, SPA fallback safety --- backend/src/middleware/security.js | 7 ++++++- backend/src/server.js | 27 +++++++++++++++++---------- 2 files changed, 23 insertions(+), 11 deletions(-) diff --git a/backend/src/middleware/security.js b/backend/src/middleware/security.js index 4129c02..2badf8f 100644 --- a/backend/src/middleware/security.js +++ b/backend/src/middleware/security.js @@ -9,10 +9,15 @@ export const setupSecurity = (app) => { directives: { defaultSrc: ["'self'"], styleSrc: ["'self'", "'unsafe-inline'"], - scriptSrc: ["'self'"], + scriptSrc: ["'self'", "'unsafe-inline'", 'https://static.cloudflareinsights.com'], + scriptSrcElem: ["'self'", "'unsafe-inline'", 'https://static.cloudflareinsights.com'], imgSrc: ["'self'", 'data:', 'https:'], + connectSrc: ["'self'", 'https:', 'wss:'], + workerSrc: ["'self'", 'blob:'], + fontSrc: ["'self'", 'https:', 'data:'], }, }, + crossOriginEmbedderPolicy: false, })); // CORS diff --git a/backend/src/server.js b/backend/src/server.js index 7333ed6..03b5c4b 100644 --- a/backend/src/server.js +++ b/backend/src/server.js @@ -46,6 +46,17 @@ setupSecurity(app); // Body parsing app.use(express.json()); +// Serve static frontend files in production +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); +const frontendPath = path.join(__dirname, '../../public'); + +// Static files MUST come before the wildcard catch-all +app.use(express.static(frontendPath, { + maxAge: '1d', + etag: true, +})); + // Routes app.use('/api/options', optionsFlowRouter); app.use('/api/analysis', dailyAnalysisRouter); @@ -61,19 +72,15 @@ app.use('/api/market', marketAnalysisRouter); app.use('/api/backtest', backtestRouter); app.use('/health', healthRouter); -// Serve static frontend files in production -const __filename = fileURLToPath(import.meta.url); -const __dirname = path.dirname(__filename); -const frontendPath = path.join(__dirname, '../../public'); - -app.use(express.static(frontendPath)); - -// Fallback all other routes to React's index.html +// SPA fallback — only for non-API, non-asset routes app.get('*', (req, res, next) => { - if (req.path.startsWith('/api/') || req.path.startsWith('/health')) { + if (req.path.startsWith('/api/') || req.path.startsWith('/health') || req.path.startsWith('/assets/')) { return next(); } - res.sendFile(path.join(frontendPath, 'index.html')); + const indexPath = path.join(frontendPath, 'index.html'); + res.sendFile(indexPath, (err) => { + if (err) next(err); + }); }); // Error handler (must be last)