2021-06-18 15:14:31 +02:00
|
|
|
/**
|
|
|
|
* This is the main entry point for the application, a simple server that
|
|
|
|
* runs some checks, and then serves up the app from the ./dist directory
|
2022-02-07 16:55:35 +01:00
|
|
|
* Also imports some routes for status checks/ ping and config saving
|
|
|
|
* Note: The app must first be built (yarn build) before this script is run
|
2021-06-18 15:14:31 +02:00
|
|
|
* */
|
2019-09-01 14:38:13 +02:00
|
|
|
|
2021-11-09 23:40:57 +01:00
|
|
|
/* Import built-in Node server modules */
|
|
|
|
const http = require('http');
|
2021-11-08 21:17:48 +01:00
|
|
|
const path = require('path');
|
2021-06-04 20:57:43 +02:00
|
|
|
const util = require('util');
|
|
|
|
const dns = require('dns');
|
|
|
|
const os = require('os');
|
2021-11-09 23:40:57 +01:00
|
|
|
|
|
|
|
/* Import Express + middleware functions */
|
|
|
|
const express = require('express');
|
2021-10-13 21:02:13 +02:00
|
|
|
const history = require('connect-history-api-fallback');
|
2021-06-04 20:57:43 +02:00
|
|
|
|
2021-07-25 18:43:47 +02:00
|
|
|
/* Kick of some basic checks */
|
|
|
|
require('./services/update-checker'); // Checks if there are any updates available, prints message
|
2023-11-23 07:02:08 +01:00
|
|
|
let config = {}; // setup the config
|
|
|
|
config = require('./services/config-validator'); // Include and kicks off the config file validation script
|
2021-07-25 18:43:47 +02:00
|
|
|
|
2021-09-17 23:40:39 +02:00
|
|
|
/* Include route handlers for API endpoints */
|
2021-09-18 00:51:02 +02:00
|
|
|
const statusCheck = require('./services/status-check'); // Used by the status check feature, uses GET
|
2021-06-18 19:01:42 +02:00
|
|
|
const saveConfig = require('./services/save-config'); // Saves users new conf.yml to file-system
|
2021-06-19 20:21:32 +02:00
|
|
|
const rebuild = require('./services/rebuild-app'); // A script to programmatically trigger a build
|
2021-12-16 05:03:36 +01:00
|
|
|
const systemInfo = require('./services/system-info'); // Basic system info, for resource widget
|
|
|
|
const sslServer = require('./services/ssl-server'); // TLS-enabled web server
|
2021-12-19 21:05:15 +01:00
|
|
|
const corsProxy = require('./services/cors-proxy'); // Enables API requests to CORS-blocked services
|
2023-11-17 07:00:48 +01:00
|
|
|
const getUser = require('./services/get-user'); // Enables server side user lookup
|
2021-06-14 21:42:02 +02:00
|
|
|
|
2021-09-17 23:40:39 +02:00
|
|
|
/* Helper functions, and default config */
|
|
|
|
const printMessage = require('./services/print-message'); // Function to print welcome msg on start
|
|
|
|
const ENDPOINTS = require('./src/utils/defaults').serviceEndpoints; // API endpoint URL paths
|
|
|
|
|
2021-06-18 15:14:31 +02:00
|
|
|
/* Checks if app is running within a container, from env var */
|
2021-06-10 20:46:46 +02:00
|
|
|
const isDocker = !!process.env.IS_DOCKER;
|
|
|
|
|
|
|
|
/* Checks env var for port. If undefined, will use Port 80 for Docker, or 4000 for metal */
|
2021-06-11 21:42:32 +02:00
|
|
|
const port = process.env.PORT || (isDocker ? 80 : 4000);
|
2019-09-01 14:38:13 +02:00
|
|
|
|
2022-05-21 23:58:59 +02:00
|
|
|
/* Checks env var for host. If undefined, will use 0.0.0.0 */
|
|
|
|
const host = process.env.HOST || '0.0.0.0';
|
|
|
|
|
2021-06-18 15:14:31 +02:00
|
|
|
/* Attempts to get the users local IP, used as part of welcome message */
|
2021-06-04 20:57:43 +02:00
|
|
|
const getLocalIp = () => {
|
|
|
|
const dnsLookup = util.promisify(dns.lookup);
|
|
|
|
return dnsLookup(os.hostname());
|
2021-06-11 16:23:25 +02:00
|
|
|
};
|
2021-06-04 20:57:43 +02:00
|
|
|
|
2021-06-18 15:14:31 +02:00
|
|
|
/* Gets the users local IP and port, then calls to print welcome message */
|
2021-06-11 16:23:25 +02:00
|
|
|
const printWelcomeMessage = () => {
|
2022-02-07 16:55:35 +01:00
|
|
|
try {
|
|
|
|
getLocalIp().then(({ address }) => {
|
2022-05-21 23:58:59 +02:00
|
|
|
const ip = process.env.HOST || address || 'localhost';
|
2022-02-07 16:55:35 +01:00
|
|
|
console.log(printMessage(ip, port, isDocker)); // eslint-disable-line no-console
|
|
|
|
});
|
|
|
|
} catch (e) {
|
|
|
|
// Fetching info for welcome message failed, print simple msg instead
|
|
|
|
console.log(`Dashy server has started (${port})`); // eslint-disable-line no-console
|
|
|
|
}
|
2021-06-11 16:23:25 +02:00
|
|
|
};
|
2021-06-04 20:57:43 +02:00
|
|
|
|
2021-06-19 20:21:32 +02:00
|
|
|
/* Just console.warns an error */
|
2021-06-18 15:14:31 +02:00
|
|
|
const printWarning = (msg, error) => {
|
|
|
|
console.warn(`\x1b[103m\x1b[34m${msg}\x1b[0m\n`, error || ''); // eslint-disable-line no-console
|
|
|
|
};
|
|
|
|
|
2021-06-18 19:01:42 +02:00
|
|
|
/* A middleware function for Connect, that filters requests based on method type */
|
|
|
|
const method = (m, mw) => (req, res, next) => (req.method === m ? mw(req, res, next) : next());
|
|
|
|
|
2021-11-08 20:31:28 +01:00
|
|
|
const app = express()
|
2022-03-07 11:50:24 +01:00
|
|
|
// Load SSL redirection middleware
|
|
|
|
.use(sslServer.middleware)
|
2021-11-08 21:17:48 +01:00
|
|
|
// Serves up static files
|
2022-09-25 20:44:40 +02:00
|
|
|
.use(express.static(path.join(__dirname, 'user-data')))
|
2021-11-08 21:17:48 +01:00
|
|
|
.use(express.static(path.join(__dirname, 'dist')))
|
2022-08-19 11:04:38 +02:00
|
|
|
.use(express.static(path.join(__dirname, 'user-data')))
|
2022-04-27 21:45:21 +02:00
|
|
|
.use(express.static(path.join(__dirname, 'public'), { index: 'initialization.html' }))
|
2021-11-08 21:17:48 +01:00
|
|
|
// Load middlewares for parsing JSON, and supporting HTML5 history routing
|
2022-02-07 16:55:35 +01:00
|
|
|
.use(express.json({ limit: '1mb' }))
|
2021-11-08 21:17:48 +01:00
|
|
|
.use(history())
|
2021-11-08 20:31:28 +01:00
|
|
|
// GET endpoint to run status of a given URL with GET request
|
|
|
|
.use(ENDPOINTS.statusCheck, (req, res) => {
|
|
|
|
try {
|
|
|
|
statusCheck(req.url, async (results) => {
|
|
|
|
await res.end(results);
|
2021-06-19 20:21:32 +02:00
|
|
|
});
|
2021-11-08 20:31:28 +01:00
|
|
|
} catch (e) {
|
|
|
|
printWarning(`Error running status check for ${req.url}\n`, e);
|
|
|
|
}
|
|
|
|
})
|
2022-09-25 20:44:40 +02:00
|
|
|
// POST Endpoint used to save config, by writing config file to disk
|
2021-11-08 20:31:28 +01:00
|
|
|
.use(ENDPOINTS.save, method('POST', (req, res) => {
|
|
|
|
try {
|
|
|
|
saveConfig(req.body, (results) => { res.end(results); });
|
2023-11-23 07:02:08 +01:00
|
|
|
config = req.body.config; // update the config
|
2021-11-08 20:31:28 +01:00
|
|
|
} catch (e) {
|
2021-11-08 21:17:48 +01:00
|
|
|
printWarning('Error writing config file to disk', e);
|
2021-11-08 20:31:28 +01:00
|
|
|
res.end(JSON.stringify({ success: false, message: e }));
|
|
|
|
}
|
|
|
|
}))
|
|
|
|
// GET endpoint to trigger a build, and respond with success status and output
|
|
|
|
.use(ENDPOINTS.rebuild, (req, res) => {
|
|
|
|
rebuild().then((response) => {
|
|
|
|
res.end(JSON.stringify(response));
|
|
|
|
}).catch((response) => {
|
|
|
|
res.end(JSON.stringify(response));
|
2021-06-04 20:57:43 +02:00
|
|
|
});
|
2021-12-16 05:03:36 +01:00
|
|
|
})
|
|
|
|
// GET endpoint to return system info, for widget
|
|
|
|
.use(ENDPOINTS.systemInfo, (req, res) => {
|
|
|
|
try {
|
|
|
|
const results = systemInfo();
|
|
|
|
systemInfo.success = true;
|
|
|
|
res.end(JSON.stringify(results));
|
|
|
|
} catch (e) {
|
|
|
|
res.end(JSON.stringify({ success: false, message: e }));
|
|
|
|
}
|
2021-12-19 21:05:15 +01:00
|
|
|
})
|
|
|
|
// GET for accessing non-CORS API services
|
|
|
|
.use(ENDPOINTS.corsProxy, (req, res) => {
|
|
|
|
try {
|
|
|
|
corsProxy(req, res);
|
|
|
|
} catch (e) {
|
|
|
|
res.end(JSON.stringify({ success: false, message: e }));
|
|
|
|
}
|
2023-01-16 13:30:34 +01:00
|
|
|
})
|
2023-11-17 07:00:48 +01:00
|
|
|
// GET endpoint to return user info
|
|
|
|
.use(ENDPOINTS.getUser, (req, res) => {
|
|
|
|
try {
|
2023-11-23 07:02:08 +01:00
|
|
|
const user = getUser(config, req);
|
2023-11-17 07:00:48 +01:00
|
|
|
res.end(JSON.stringify(user));
|
|
|
|
} catch (e) {
|
|
|
|
res.end(JSON.stringify({ success: false, message: e }));
|
|
|
|
}
|
|
|
|
})
|
2024-02-28 12:57:25 +01:00
|
|
|
// If no other route is matched, serve up the index.html with a 404 status
|
|
|
|
.use((req, res) => {
|
|
|
|
res.status(404).sendFile(path.join(__dirname, 'dist', 'index.html'));
|
|
|
|
});
|
2021-11-08 20:31:28 +01:00
|
|
|
|
2021-11-09 23:40:57 +01:00
|
|
|
/* Create HTTP server from app on port, and print welcome message */
|
2022-02-07 16:55:35 +01:00
|
|
|
http.createServer(app)
|
2022-05-21 23:58:59 +02:00
|
|
|
.listen(port, host, () => {
|
2022-02-07 16:55:35 +01:00
|
|
|
printWelcomeMessage();
|
|
|
|
})
|
|
|
|
.on('error', (err) => {
|
|
|
|
printWarning('Unable to start Dashy\'s Node server', err);
|
|
|
|
});
|
2021-11-09 23:40:57 +01:00
|
|
|
|
|
|
|
/* Check, and if possible start SSL server too */
|
2022-03-07 11:50:24 +01:00
|
|
|
sslServer.startSSLServer(app);
|