← back to Designerrepresentatives
server.js
63 lines
require('dotenv').config();
const express = require('express');
const path = require('path');
const morgan = require('morgan');
const publicRoutes = require('./routes/public');
const app = express();
const PORT = parseInt(process.env.PORT || '9924', 10);
const PUBLIC_URL = process.env.PUBLIC_URL || `http://localhost:${PORT}`;
const IS_PROD = process.env.NODE_ENV === 'production';
app.set('trust proxy', 1);
app.set('view engine', 'ejs');
app.set('views', path.join(__dirname, 'views'));
app.disable('x-powered-by');
app.use(morgan(IS_PROD ? 'combined' : 'dev'));
app.use(express.json({ limit: '256kb' }));
app.use(express.urlencoded({ extended: true, limit: '256kb' }));
// 404-guard — never serve snapshot/backup paths from static root
app.use((req, res, next) => {
if (/\.(bak|pre-)[^/]*$|\.bak$/i.test(req.path)) {
return res.status(404).type('text').send('Not found');
}
next();
});
app.use(express.static(path.join(__dirname, 'public'), {
maxAge: '1h',
setHeaders(res, p) {
if (p.endsWith('.html')) res.setHeader('Cache-Control', 'no-store, must-revalidate');
},
}));
// Make GA + public URL available to every view
app.use((req, res, next) => {
res.locals.GA_ID = process.env.GA_ID || 'G-MVZFTCQY3X';
res.locals.PUBLIC_URL = PUBLIC_URL;
next();
});
app.use('/', publicRoutes);
app.use((req, res) => {
res.status(404).render('public/404', { title: 'Not found — Designer Representatives' });
});
// eslint-disable-next-line no-unused-vars
app.use((err, req, res, next) => {
console.error('[error]', err && err.stack ? err.stack : err);
res.status(500).render('public/error', {
title: 'Server error — Designer Representatives',
message: IS_PROD ? 'Something went wrong.' : (err && err.message) || 'Unknown error',
});
});
app.listen(PORT, () => {
console.log(`designerrepresentatives listening on :${PORT} (${IS_PROD ? 'prod' : 'dev'})`);
});