diff --git a/server.js b/server.js index 4cdc97f5..0b0485f9 100644 --- a/server.js +++ b/server.js @@ -18,7 +18,8 @@ require('./services/update-checker'); // Checks if there are any updates availab require('./services/config-validator'); // Include and kicks off the config file validation script /* Include route handlers for API endpoints */ -const statusCheck = require('./services/status-check'); // Used by the status check feature, to ping services +const statusCheck = require('./services/status-check'); // Used by the status check feature, uses GET +const statusPing = require('./services/status-ping'); // Used for ping-only status checks const saveConfig = require('./services/save-config'); // Saves users new conf.yml to file-system const rebuild = require('./services/rebuild-app'); // A script to programmatically trigger a build @@ -61,12 +62,22 @@ try { .use(serveStatic(`${__dirname}/dist`)) // During build, a custom page will be served before the app is available .use(serveStatic(`${__dirname}/public`, { index: 'default.html' })) - // This root returns the status of a given service - used for uptime monitoring + // 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); }); + } catch (e) { + printWarning(`Error running status check for ${req.url}\n`, e); + } + }) + // GET endpoint to ping a given IP address, also used for status checking + .use(ENDPOINTS.statusPing, (req, res) => { + try { + statusPing(req.url, async (results) => { + await res.end(results); + }); } catch (e) { printWarning(`Error running ping check for ${req.url}\n`, e); } @@ -74,9 +85,7 @@ try { // POST Endpoint used to save config, by writing conf.yml to disk .use(ENDPOINTS.save, method('POST', (req, res) => { try { - saveConfig(req.body, (results) => { - res.end(results); - }); + saveConfig(req.body, (results) => { res.end(results); }); } catch (e) { res.end(JSON.stringify({ success: false, message: e })); } diff --git a/services/status-ping.js b/services/status-ping.js new file mode 100644 index 00000000..dacaab26 --- /dev/null +++ b/services/status-ping.js @@ -0,0 +1,42 @@ +/** + * Short Node script for pinging an IP address to check if it's online + * Used for the optional status check feature, as an alternative to the GET request + * Accepts a single ip param, will ping that server, then respond with the status + * Credit to @nospaceships for the node-net-ping package, MIT + */ +const ping = require('net-ping'); + +/* Options used for ping */ +const pingOptions = { + networkProtocol: ping.NetworkProtocol.IPv4, + packetSize: 16, + retries: 1, + timeout: 1000, + ttl: 128, +}; + +/* Kicks of an IP ping, and returns callback with the status */ +const makePing = (ip, render) => { + const startTime = new Date(); + const session = ping.createSession(pingOptions); + session.pingHost(ip, (error, target) => { + const timeTaken = (new Date() - startTime); + if (error) { + render(JSON.stringify({ success: false, message: `❌ ${error}` })); + } else { + render(JSON.stringify({ success: true, message: `✅ ${target} is Alive\n⏱️ Took ${timeTaken} ms` })); + } + session.close(); + }); +}; + +/* Checks if a given IP address is online, and accessible */ +module.exports = (paramStr, render) => { + if (!paramStr || !paramStr.includes('ip=')) { + render(JSON.stringify({ success: false, message: '❌ Malformed or Missing IP' })); + } else { + // Prepare the parameters, which are got from the URL + const ip = decodeURIComponent((new URLSearchParams(paramStr)).get('ip')); + makePing(ip, render); + } +};