mirror of
https://github.com/ptarmiganlabs/butler-sos.git
synced 2025-12-19 17:58:18 -05:00
feat: Add custom 404 page for config visualisation server
This commit is contained in:
@@ -9,6 +9,50 @@ import handlebars from 'handlebars';
|
|||||||
import globals from '../globals.js';
|
import globals from '../globals.js';
|
||||||
import configObfuscate from './config-obfuscate.js';
|
import configObfuscate from './config-obfuscate.js';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Serves the custom 404 error page
|
||||||
|
*
|
||||||
|
* @param {object} request - The Fastify request object
|
||||||
|
* @param {object} reply - The Fastify reply object
|
||||||
|
* @returns {void}
|
||||||
|
*/
|
||||||
|
async function serve404Page(request, reply) {
|
||||||
|
try {
|
||||||
|
let template404;
|
||||||
|
const host = globals.config.get('Butler-SOS.configVisualisation.host');
|
||||||
|
const port = globals.config.get('Butler-SOS.configVisualisation.port');
|
||||||
|
|
||||||
|
if (globals.isSea) {
|
||||||
|
// In SEA mode, get the 404 template via sea.getAsset
|
||||||
|
globals.logger.verbose(`CONFIG VIS: Getting 404.html template via sea.getAsset`);
|
||||||
|
template404 = sea.getAsset('/404.html', 'utf8');
|
||||||
|
if (!template404) {
|
||||||
|
globals.logger.error(`CONFIG VIS: Could not find 404.html template in SEA assets`);
|
||||||
|
reply.code(404).send({ error: 'Page not found' });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// In Node.js mode, read from filesystem
|
||||||
|
const filePath = path.resolve(globals.appBasePath, 'static', '404.html');
|
||||||
|
globals.logger.verbose(`CONFIG VIS: Reading 404.html template from ${filePath}`);
|
||||||
|
template404 = fs.readFileSync(filePath, 'utf8');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compile handlebars template and replace variables
|
||||||
|
const compiledTemplate = handlebars.compile(template404);
|
||||||
|
const renderedHtml = compiledTemplate({
|
||||||
|
visTaskHost: host,
|
||||||
|
visTaskPort: port,
|
||||||
|
});
|
||||||
|
|
||||||
|
// Send 404 response with custom page
|
||||||
|
reply.code(404).header('Content-Type', 'text/html; charset=utf-8').send(renderedHtml);
|
||||||
|
} catch (err) {
|
||||||
|
globals.logger.error(`CONFIG VIS: Error serving 404 page: ${err.message}`);
|
||||||
|
reply.code(404).send({ error: 'Page not found' });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets up and starts a web server for visualizing Butler SOS configuration.
|
* Sets up and starts a web server for visualizing Butler SOS configuration.
|
||||||
*
|
*
|
||||||
@@ -107,7 +151,8 @@ export async function setupConfigVisServer(logger, config) {
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (!content) {
|
if (!content) {
|
||||||
reply.code(404).send({ error: 'File not found' });
|
// File not found - serve custom 404 page
|
||||||
|
await serve404Page(request, reply);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -116,6 +161,29 @@ export async function setupConfigVisServer(logger, config) {
|
|||||||
globals.logger.error(
|
globals.logger.error(
|
||||||
`CONFIG VIS: Error serving static file in SEA mode: ${err.message}`
|
`CONFIG VIS: Error serving static file in SEA mode: ${err.message}`
|
||||||
);
|
);
|
||||||
|
await serve404Page(request, reply);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Add specific handler for the butler-sos.png file at the root path
|
||||||
|
configVisServer.get('/butler-sos.png', async (request, reply) => {
|
||||||
|
try {
|
||||||
|
// Get the asset from SEA
|
||||||
|
const logoContent = sea.getAsset('/butler-sos.png');
|
||||||
|
|
||||||
|
if (!logoContent) {
|
||||||
|
globals.logger.error(
|
||||||
|
`CONFIG VIS: Could not find butler-sos.png in SEA assets`
|
||||||
|
);
|
||||||
|
reply.code(404).send({ error: 'Logo not found' });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
reply.code(200).header('Content-Type', 'image/png').send(logoContent);
|
||||||
|
} catch (err) {
|
||||||
|
globals.logger.error(
|
||||||
|
`CONFIG VIS: Error serving logo in SEA mode: ${err.message}`
|
||||||
|
);
|
||||||
reply.code(500).send({ error: 'Internal server error' });
|
reply.code(500).send({ error: 'Internal server error' });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -147,6 +215,9 @@ export async function setupConfigVisServer(logger, config) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set up a global 404 handler for both running modes
|
||||||
|
configVisServer.setNotFoundHandler(serve404Page);
|
||||||
|
|
||||||
configVisServer.get('/', async (request, reply) => {
|
configVisServer.get('/', async (request, reply) => {
|
||||||
// Obfuscate the config object before sending it to the client
|
// Obfuscate the config object before sending it to the client
|
||||||
// First get clean copy of the config object
|
// First get clean copy of the config object
|
||||||
|
|||||||
@@ -5,15 +5,8 @@
|
|||||||
"assets": {
|
"assets": {
|
||||||
"package.json": "./package.json",
|
"package.json": "./package.json",
|
||||||
"/404.html": "./static/404.html",
|
"/404.html": "./static/404.html",
|
||||||
"/android-chrome-192x192.png": "./static/android-chrome-192x192.png",
|
"/logo.png": "./static/logo.png",
|
||||||
"/android-chrome-512x512.png": "./static/android-chrome-512x512.png",
|
|
||||||
"/apple-touch-icon.png": "./static/apple-touch-icon.png",
|
|
||||||
"/butler-sos.png": "./static/ctrl-q.png",
|
|
||||||
"/favicon-16x16.png": "./static/favicon-16x16.png",
|
|
||||||
"/favicon-32x32.png": "./static/favicon-32x32.png",
|
|
||||||
"/favicon.ico": "./static/favicon.ico",
|
|
||||||
"/index.html": "./static/index.html",
|
"/index.html": "./static/index.html",
|
||||||
"/logo.svg": "./static/logo.svg",
|
|
||||||
"/configvis/butler-sos.png": "./static/configvis/butler-sos.png",
|
"/configvis/butler-sos.png": "./static/configvis/butler-sos.png",
|
||||||
"/configvis/download-solid.svg": "./static/configvis/download-solid.svg",
|
"/configvis/download-solid.svg": "./static/configvis/download-solid.svg",
|
||||||
"/configvis/index.html": "./static/configvis/index.html",
|
"/configvis/index.html": "./static/configvis/index.html",
|
||||||
|
|||||||
47
static/404.html
Normal file
47
static/404.html
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>404 Not Found</title>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
text-align: center;
|
||||||
|
padding: 150px;
|
||||||
|
}
|
||||||
|
h1 {
|
||||||
|
font-size: 50px;
|
||||||
|
}
|
||||||
|
body {
|
||||||
|
font:
|
||||||
|
20px Helvetica,
|
||||||
|
sans-serif;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
article {
|
||||||
|
display: block;
|
||||||
|
text-align: left;
|
||||||
|
width: 650px;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
a {
|
||||||
|
color: #dc8100;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
a:hover {
|
||||||
|
color: #333;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<article>
|
||||||
|
<img src="/butler-sos.png" alt="Butler SOS logo" style="height: 200px" />
|
||||||
|
<h1>Err. That's an error.</h1>
|
||||||
|
<p>The page you were looking for could not be found.</p>
|
||||||
|
<!-- Open in new tab -->
|
||||||
|
<p>
|
||||||
|
This really shouldn't happen, so please open a ticket in the Butler SOS bug tracker
|
||||||
|
<a target="_blank" href="https://github.com/ptarmiganlabs/butler-sos/issues/new/choose">on GitHub</a>.
|
||||||
|
</p>
|
||||||
|
</article>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
BIN
static/logo.png
Normal file
BIN
static/logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 29 KiB |
File diff suppressed because one or more lines are too long
|
Before Width: | Height: | Size: 31 KiB |
Reference in New Issue
Block a user