blob: f346887111ffb487bbc452cf182707a5f853dd3b [file] [log] [blame]
import bodyParser from 'body-parser';
import dotenv from 'dotenv';
import express from 'express';
import morgan from 'morgan';
import path from 'path';
import fs from 'fs';
import http from 'http';
import https from 'https';
import session from 'express-session';
import * as appInsights from 'applicationinsights';
import ProxyAgent from 'proxy-agent';
import {
APP_INSIGHTS_CONNECTION_STRING,
PROXY_URL,
SSL,
SESSION_STORE,
} from './config';
import setRoutes from './routes';
const isProd = process.env.NODE_ENV === 'production';
const httpsProxyAgent = PROXY_URL ? new ProxyAgent(PROXY_URL) : null;
if (APP_INSIGHTS_CONNECTION_STRING) {
appInsights
.setup(APP_INSIGHTS_CONNECTION_STRING)
.setAutoDependencyCorrelation(true)
.setAutoCollectRequests(true)
.setAutoCollectPerformance(true, true)
.setAutoCollectExceptions(true)
.setAutoCollectDependencies(true)
.setAutoCollectConsole(true)
.setUseDiskRetryCaching(true)
.setSendLiveMetrics(false)
.setDistributedTracingMode(appInsights.DistributedTracingModes.AI)
.start();
}
if (httpsProxyAgent && isProd) {
// NOTES:
//
// - `defaultClient` property on `appInsights` doesn't exist
// until `.start` is called
//
// - in development on our laptop (as opposed to a server)
// we don't need to go through a proxy.
appInsights.defaultClient.config.httpsAgent = httpsProxyAgent;
}
const app = express();
const server = http.createServer(app);
dotenv.load({ path: '.env' });
app.set('port', process.env.PORT || 4200);
const secretToken = process.env.SECRET_TOKEN;
if (!secretToken || secretToken === 'promiseyouwillchangeit') {
if (isProd) {
throw new Error('Please change your SECRET_TOKEN env');
} else {
console.warn(
'Remember to change your SECRET_TOKEN env before deploying to PROD'
);
}
}
app.use('/', express.static(path.join(__dirname, '../public')));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(
session({
store: SESSION_STORE,
secret: secretToken,
resave: true,
saveUninitialized: true,
cookie: { expires: new Date(2147483647000) },
})
);
if (APP_INSIGHTS_CONNECTION_STRING) {
app.use(function appInsightsMiddleWare(req, res, next) {
appInsights.defaultClient.trackNodeHttpRequest({
request: req,
response: res,
});
next();
});
}
app.use(morgan('dev'));
app.use((req, res, next) => {
const {
headers: { cookie },
} = req;
if (cookie) {
const values = cookie.split(';').reduce((res, item) => {
const data = item.trim().split('=');
return { ...res, [data[0]]: data[1] };
}, {});
res.locals.cookie = values;
} else res.locals.cookie = {};
next();
});
setRoutes(app);
app.get('/*', function (_req, res) {
res.sendFile(path.join(__dirname, '../public/index.html'));
});
server.listen(app.get('port'), () => {
console.log(`App is listening on port ${app.get('port')} as HTTP`);
});
process.on('uncaughtException', function (err) {
console.error('uncaughtException: ' + err.message);
console.error(err.stack);
});
// setup SSL
if (SSL.port > 0 && fs.existsSync(SSL.keyfile) && fs.existsSync(SSL.certfile)) {
const credentials: any = {
key: fs.readFileSync(SSL.keyfile, 'ascii'),
cert: fs.readFileSync(SSL.certfile, 'ascii'),
ca: [],
};
if (fs.existsSync(SSL.passfile)) {
credentials.passphrase = fs.readFileSync(SSL.passfile, 'ascii').trim();
}
if (SSL.cafiles) {
SSL.cafiles.forEach((cafile) => {
if (fs.existsSync(cafile)) {
credentials.ca.push(fs.readFileSync(cafile, 'ascii'));
}
});
}
const httpsServer = https.createServer(credentials, app);
httpsServer.listen(SSL.port, () => {
console.log(`App is listening on port ${SSL.port} as HTTPS`);
});
}
export { app };