modified: backend/src/server.ts
This commit is contained in:
@@ -23,12 +23,15 @@ import dynamicRoutes from './routes/dynamic';
|
|||||||
|
|
||||||
const app: Express = express();
|
const app: Express = express();
|
||||||
|
|
||||||
|
// Trust proxy if behind reverse proxy (nginx, apache, etc)
|
||||||
|
app.set('trust proxy', true);
|
||||||
|
|
||||||
// Middleware
|
// Middleware
|
||||||
app.use(helmet({
|
app.use(helmet({
|
||||||
contentSecurityPolicy: config.nodeEnv === 'production' ? {
|
contentSecurityPolicy: config.nodeEnv === 'production' ? {
|
||||||
directives: {
|
directives: {
|
||||||
defaultSrc: ["'self'"],
|
defaultSrc: ["'self'"],
|
||||||
scriptSrc: ["'self'", "'unsafe-inline'", "blob:"],
|
scriptSrc: ["'self'", "'unsafe-inline'", "'unsafe-eval'", "blob:"],
|
||||||
workerSrc: ["'self'", "blob:"],
|
workerSrc: ["'self'", "blob:"],
|
||||||
styleSrc: ["'self'", "'unsafe-inline'"],
|
styleSrc: ["'self'", "'unsafe-inline'"],
|
||||||
imgSrc: ["'self'", "data:", "blob:"],
|
imgSrc: ["'self'", "data:", "blob:"],
|
||||||
@@ -36,6 +39,9 @@ app.use(helmet({
|
|||||||
connectSrc: ["'self'"],
|
connectSrc: ["'self'"],
|
||||||
},
|
},
|
||||||
} : false,
|
} : false,
|
||||||
|
crossOriginOpenerPolicy: false,
|
||||||
|
crossOriginResourcePolicy: false,
|
||||||
|
crossOriginEmbedderPolicy: false,
|
||||||
}));
|
}));
|
||||||
app.use(cors());
|
app.use(cors());
|
||||||
app.use(express.json());
|
app.use(express.json());
|
||||||
@@ -96,12 +102,22 @@ app.use('/api/v1', dynamicRoutes);
|
|||||||
// Serve frontend static files in production
|
// Serve frontend static files in production
|
||||||
if (config.nodeEnv === 'production') {
|
if (config.nodeEnv === 'production') {
|
||||||
const frontendPath = path.join(__dirname, '../../frontend/dist');
|
const frontendPath = path.join(__dirname, '../../frontend/dist');
|
||||||
app.use(express.static(frontendPath));
|
console.log(`📁 Serving static files from: ${frontendPath}`);
|
||||||
|
|
||||||
|
app.use(express.static(frontendPath, {
|
||||||
|
maxAge: '1d',
|
||||||
|
etag: true,
|
||||||
|
setHeaders: (res) => {
|
||||||
|
res.setHeader('Cache-Control', 'public, max-age=86400');
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
// SPA fallback - all non-API routes serve index.html
|
// SPA fallback - all non-API routes serve index.html
|
||||||
app.get('*', (req: Request, res: Response) => {
|
app.get('*', (req: Request, res: Response) => {
|
||||||
if (!req.path.startsWith('/api/') && !req.path.startsWith('/api-docs') && req.path !== '/health') {
|
if (!req.path.startsWith('/api/') && !req.path.startsWith('/api-docs') && req.path !== '/health') {
|
||||||
res.sendFile(path.join(frontendPath, 'index.html'));
|
const indexPath = path.join(frontendPath, 'index.html');
|
||||||
|
console.log(`📄 Serving index.html for route: ${req.path}`);
|
||||||
|
res.sendFile(indexPath);
|
||||||
} else {
|
} else {
|
||||||
res.status(404).json({ error: 'API route not found' });
|
res.status(404).json({ error: 'API route not found' });
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user