198 lines
5.3 KiB
JavaScript
198 lines
5.3 KiB
JavaScript
import serveIndex from 'serve-index';
|
|
import open from 'open';
|
|
const module = 'web'; // Module Name
|
|
import { load_config, log } from '../nwa-lib/index.js';
|
|
const config = load_config();
|
|
|
|
log(`${module}: Loaded module: ${module}`);
|
|
|
|
import fs from 'fs';
|
|
import path from 'path';
|
|
import { parse } from 'csv-parse';
|
|
import express from 'express';
|
|
const app = express();
|
|
|
|
|
|
// Serve config as JSON
|
|
app.get('/api/config', (req, res) => {
|
|
res.json(config);
|
|
|
|
let webreqmeta = {
|
|
method: req.method,
|
|
url: req.originalUrl,
|
|
ip: req.ip,
|
|
userAgent: req.get('User-Agent')
|
|
};
|
|
|
|
log(module + ': WEBAPI: ' + JSON.stringify(webreqmeta))
|
|
});
|
|
|
|
// Serve sidepanel nav as JSON
|
|
app.get('/api/nav/sidepanel', (req, res) => {
|
|
const sideMenuPath = path.join(
|
|
config.dirs.html,
|
|
'conf',
|
|
'nav-sidepanel.json'
|
|
);
|
|
|
|
try {
|
|
const sideMenuData = JSON.parse(
|
|
fs.readFileSync(sideMenuPath, 'utf8')
|
|
);
|
|
res.json(sideMenuData);
|
|
|
|
log(module + ': INFO: GET /api/nav/sidepanel');
|
|
} catch (err) {
|
|
log(`ERROR: GET /api/nav/sidepanel failed: ${err}`);
|
|
res.status(500).json({ error: 'Failed to load nav-sidepanel.json' });
|
|
}
|
|
});
|
|
|
|
|
|
// Serve nav as JSON
|
|
app.get('/api/nav', (req, res) => {
|
|
const menuPath = (path.join(config.dirs.html, 'conf', 'nav.json'));
|
|
|
|
try {
|
|
const menuData = JSON.parse(fs.readFileSync(menuPath, 'utf8'));
|
|
res.json(menuData);
|
|
|
|
log(module + ': INFO: GET /api/nav');
|
|
} catch (err) {
|
|
log(`ERROR: GET /api/nav failed: ${err}`);
|
|
res.status(500).json({ error: 'Failed to load nav.json' });
|
|
}
|
|
});
|
|
|
|
// API
|
|
app.get ('/api', (req, res) => {
|
|
res.json(gen_api_usage(req));
|
|
|
|
let webreqmeta = {
|
|
method: req.method,
|
|
url: req.originalUrl,
|
|
ip: req.ip,
|
|
userAgent: req.get('User-Agent')
|
|
};
|
|
|
|
log(module + ': WEBAPI: ' + JSON.stringify(webreqmeta))
|
|
});
|
|
|
|
|
|
|
|
// /img
|
|
app.use('/img', logStaticRequests('img'), express.static(path.join(config.dirs.html, 'img')));
|
|
|
|
// /css
|
|
app.use('/css', logStaticRequests('css'), express.static(path.join(config.dirs.html, 'css')));
|
|
|
|
// /js
|
|
app.use('/js', logStaticRequests('js'), express.static(path.join(config.dirs.html, 'js')));
|
|
|
|
|
|
// md
|
|
app.use('/md', logStaticRequests('md'), express.static(path.join(config.dirs.html, 'md')));
|
|
|
|
|
|
// Web Libs
|
|
for (let wl in config.modules.web.weblibs) {
|
|
log(`${module}: Serving WebLib: /${wl} at ${path.join(config.dirs.app, 'node_modules', config.modules.web.weblibs[wl])}`)
|
|
app.use('/' + wl, logStaticRequests(wl), express.static(path.join(config.dirs.app, 'node_modules', config.modules.web.weblibs[wl])));
|
|
}
|
|
|
|
|
|
// Top Level Website
|
|
app.use('/', logStaticRequests('html'), express.static(path.join(config.dirs.html)));
|
|
|
|
// Catch-all for 404 Not Found
|
|
app.use((req, res, next) => {
|
|
const webreqmeta = {
|
|
method: req.method,
|
|
url: req.originalUrl,
|
|
ip: req.ip,
|
|
userAgent: req.get('User-Agent')
|
|
};
|
|
|
|
log(`404 NOT FOUND: ${JSON.stringify(webreqmeta)}`);
|
|
|
|
if (req.originalUrl.startsWith('/api/')) {
|
|
res.status(404).json({ error: 'Not Found', path: req.originalUrl });
|
|
} else {
|
|
res.status(404).sendFile(path.join(config.dirs.html, '404.html'));
|
|
}
|
|
});
|
|
|
|
// Starting Web Server
|
|
const bindAddrs =
|
|
Array.isArray(config.modules[module].bind_ip_addrs) &&
|
|
config.modules[module].bind_ip_addrs.length > 0
|
|
? config.modules[module].bind_ip_addrs
|
|
: ['0.0.0.0'];
|
|
|
|
for (const ip_addr of bindAddrs) {
|
|
if (ip_addr === '0.0.0.0') {
|
|
const server = app.listen(config.modules[module].port, '0.0.0.0', () => {
|
|
for (const ip of config.host.ips) {
|
|
log(`INFO: WebUI running at http://${ip}:${config.modules[module].port}`, true);
|
|
|
|
if (config.modules[module].open_browser && ip === '127.0.0.1') {
|
|
open(`http://127.0.0.1:${config.modules[module].port}`);
|
|
}
|
|
}
|
|
});
|
|
|
|
server.on('error', (err) => {
|
|
log(`ERROR: WebUI failed to start on 0.0.0.0:${config.modules[module].port}: ${err}`, true);
|
|
});
|
|
} else {
|
|
const server = app.listen(config.modules[module].port, ip_addr, () => {
|
|
log(`INFO: WebUI running at http://${ip_addr}:${config.modules[module].port}`, true);
|
|
if (config.modules[module].open_browser) {
|
|
open(`http://${ip_addr}:${config.modules[module].port}`);
|
|
}
|
|
});
|
|
|
|
server.on('error', (err) => {
|
|
log(`ERROR: WebUI failed to start on ${ip_addr}:${config.modules[module].port}: ${err}`, true);
|
|
});
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ----------- Libraries -------------
|
|
function logStaticRequests(subdir) {
|
|
const func = 'logStaticRequests';
|
|
return (req, res, next) => {
|
|
const webreqmeta = {
|
|
method: req.method,
|
|
url: req.originalUrl,
|
|
ip: req.ip,
|
|
userAgent: req.get('User-Agent'),
|
|
type: subdir
|
|
};
|
|
log(`${module}: ${func}: Web Req: ${JSON.stringify(webreqmeta)}`);
|
|
next();
|
|
};
|
|
}
|
|
|
|
|
|
// API Usage
|
|
function gen_api_usage(req) {
|
|
// let base_url = "http://localhost:" + config.web.port;
|
|
const base_url = `${req.protocol}://${req.headers.host}`;
|
|
let usage = {};
|
|
|
|
usage['API'] = {}
|
|
usage['API']['DESC'] = "API"
|
|
usage['API']['URL'] = base_url + '/api';
|
|
|
|
usage['API']['CONFIG'] = {}
|
|
usage['API']['CONFIG']['DESC'] = "API Config JSON"
|
|
usage['API']['CONFIG']['URL'] = base_url + '/api/config';
|
|
|
|
return usage;
|
|
}
|