Improve error handling for missing config and static assets.

This commit is contained in:
John Furrow
2017-10-16 22:59:20 -07:00
parent b88c7ff119
commit 265fa899f5
5 changed files with 150 additions and 97 deletions
+2 -2
View File
@@ -8,10 +8,10 @@
"build-assets": "UPDATED_SCRIPT=build npm run deprecated-warning && npm run build",
"lint": "eslint .",
"deprecated-warning": "node client/scripts/deprecated-warning.js && sleep 10",
"start:development:server": "NODE_ENV=development nodemon server/bin/www",
"start:development:server": "NODE_ENV=development nodemon server/bin/start.js",
"start:development": "UPDATED_SCRIPT=start:development:server npm run deprecated-warning && npm run start:development:server",
"start:production": "UPDATED_SCRIPT=start npm run deprecated-warning && npm start",
"start": "node server/bin/www",
"start": "node server/bin/start.js",
"start:watch": "UPDATED_SCRIPT=start:development:client npm run deprecated-warning && npm run start:development:client",
"start:development:client": "node client/scripts/start.js"
},
+44
View File
@@ -0,0 +1,44 @@
'use strict';
const checkRequiredFiles = require('react-dev-utils/checkRequiredFiles');
const fs = require('fs');
const path = require('path');
const staticAssets = [
path.join(__dirname, '../assets/index.html')
];
const configFiles = [
path.join(__dirname, '../../config.js')
];
// Taken from react-scripts/check-required-files, but without console.logs.
const doFilesExist = files => {
let currentFilePath;
try {
files.forEach(filename => {
currentFilePath = filename;
fs.accessSync(filename, fs.F_OK);
});
return true;
} catch (err) {
return false;
}
};
const enforcePrerequisites = () => {
return new Promise((resolve, reject) => {
if (!doFilesExist(configFiles)) {
reject(`Configuration files missing. Please check the 'Configuring' section of README.md.`);
return;
}
if (!doFilesExist(staticAssets)) {
reject(`Static assets (index.html) are missing. Please check the 'Compiling assets and starting the server' section of README.md.`);
return;
}
return resolve();
});
};
module.exports = enforcePrerequisites;
+12
View File
@@ -0,0 +1,12 @@
'use strict';
const chalk = require('chalk');
const enforcePrerequisites = require('./enforce-prerequisites');
const {startWebServer} = require('./web-server');
enforcePrerequisites().then(startWebServer).catch((error) => {
console.log(chalk.red('Failed to start web server:'));
console.log(chalk.cyan(error));
process.exit(1);
});
+92
View File
@@ -0,0 +1,92 @@
'use strict';
const startWebServer = () => {
const chalk = require('chalk');
const debug = require('debug')('flood:server');
const fs = require('fs');
const app = require('../app');
const config = require('../../config');
const port = normalizePort(config.floodServerPort);
const host = config.floodServerHost;
const useSSL = config.ssl;
app.set('port', port);
app.set('host', host);
// Create HTTP or HTTPS server.
let server;
if (useSSL) {
if (!config.sslKey || !config.sslCert){
console.error('Cannot start HTTPS server, `sslKey` or `sslCert`' +
' is missing in config.js.');
process.exit(1);
}
server = require('spdy').createServer({
key: fs.readFileSync(config.sslKey),
cert: fs.readFileSync(config.sslCert)
}, app);
} else {
server = require('http').createServer(app);
}
// Listen on provided port, on all network interfaces.
server.listen(port, host);
server.on('error', onError);
server.on('listening', onListening);
// Normalize a port into a number, string, or false.
function normalizePort(val) {
let port = parseInt(val, 10);
// Named pipe.
if (isNaN(port)) {
return val;
}
// Port number.
if (port >= 0) {
return port;
}
return false;
}
function onError(error) {
if (error.syscall !== 'listen') {
throw error;
}
let bind = typeof port === 'string' ? 'Pipe ' + port : 'Port ' + port;
// Handle specific listen errors with friendly messages.
switch (error.code) {
case 'EACCES':
console.error(bind + ' requires elevated privileges');
process.exit(1);
break;
case 'EADDRINUSE':
console.error(bind + ' is already in use');
process.exit(1);
break;
default:
throw error;
}
}
// Event listener for HTTP server "listening" event.
function onListening() {
let addr = server.address();
let bind = typeof addr === 'string' ? 'pipe ' + addr : 'port ' + addr.port;
debug('Listening on ' + bind);
}
const address = chalk.underline(`${useSSL ? 'https' : 'http'}://${host}:${port}`);
console.log(chalk.green(`Flood server starting on ${address}.\n`));
};
module.exports = {startWebServer};
-95
View File
@@ -1,95 +0,0 @@
#!/usr/bin/env node
'use strict';
const fs = require('fs');
// Ensure we have a user-defined config.js for use throughout the app.
try {
fs.accessSync(__dirname + '/../../config.js', fs.F_OK);
} catch (error) {
throw new Error('Cannot start Flood server, config.js is missing. Copy ' +
'config.template.js to config.js.');
process.exit(1);
}
const app = require('../app');
const config = require('../../config');
const debug = require('debug')('flood:server');
const port = normalizePort(config.floodServerPort);
const host = config.floodServerHost;
const useSSL = config.ssl;
app.set('port', port);
app.set('host', host);
// Create HTTP or HTTPS server.
let server;
if (useSSL) {
if (!config.sslKey || !config.sslCert){
console.error('Cannot start HTTPS server, `sslKey` or `sslCert`' +
' is missing in config.js.');
process.exit(1);
}
server = require('spdy').createServer({
key: fs.readFileSync(config.sslKey),
cert: fs.readFileSync(config.sslCert)
}, app);
} else {
server = require('http').createServer(app);
}
// Listen on provided port, on all network interfaces.
server.listen(port, host);
server.on('error', onError);
server.on('listening', onListening);
// Normalize a port into a number, string, or false.
function normalizePort(val) {
let port = parseInt(val, 10);
// Named pipe.
if (isNaN(port)) {
return val;
}
// Port number.
if (port >= 0) {
return port;
}
return false;
}
function onError(error) {
if (error.syscall !== 'listen') {
throw error;
}
let bind = typeof port === 'string' ? 'Pipe ' + port : 'Port ' + port;
// Handle specific listen errors with friendly messages.
switch (error.code) {
case 'EACCES':
console.error(bind + ' requires elevated privileges');
process.exit(1);
break;
case 'EADDRINUSE':
console.error(bind + ' is already in use');
process.exit(1);
break;
default:
throw error;
}
}
// Event listener for HTTP server "listening" event.
function onListening() {
let addr = server.address();
let bind = typeof addr === 'string' ? 'pipe ' + addr : 'port ' + addr.port;
debug('Listening on ' + bind);
}
console.log(`\nFlood server starting on ${useSSL ? 'https' : 'http'}://${host}:${port}.\n`);