hastebin/lib/template_handler.js

75 lines
2.3 KiB
JavaScript

/**
* Template Handler Middleware
* Handles injecting CSP nonces into HTML templates
*/
const fs = require('fs');
const path = require('path');
const winston = require('winston');
// Cache for HTML templates
const templateCache = {};
/**
* Template handler middleware
* Preprocesses HTML templates and injects the CSP nonce
*/
function templateHandlerMiddleware(staticDir) {
// Load the index.html template at startup to avoid reading from disk on each request
try {
const indexPath = path.join(staticDir, 'index.html');
templateCache[indexPath] = fs.readFileSync(indexPath, 'utf8');
winston.debug('Loaded template: ' + indexPath);
} catch (err) {
winston.error('Failed to load index.html template at startup:', err);
}
return function(req, res, next) {
// Only process specific URLs
if (req.url === '/' || req.url.match(/^\/[a-zA-Z0-9_-]+$/)) {
const indexPath = path.join(staticDir, 'index.html');
// If template is not in cache, try to load it
if (!templateCache[indexPath]) {
try {
templateCache[indexPath] = fs.readFileSync(indexPath, 'utf8');
winston.debug('Loaded template on demand: ' + indexPath);
} catch (err) {
winston.error('Error reading index.html template:', err);
return next();
}
}
// Get the CSP nonce from the request (set by CSP middleware)
const nonce = req.cspNonce || '';
// Add debug log
console.log('Template handler processing with nonce:', nonce);
// Process the template - replace all nonce placeholders
let html;
try {
html = templateCache[indexPath].replace(/\{\{cspNonce\}\}/g, nonce);
} catch (err) {
winston.error('Error processing template:', err);
return next();
}
// Set response headers for HTML content
res.setHeader('Content-Type', 'text/html; charset=utf-8');
res.setHeader('Content-Length', Buffer.byteLength(html));
// Send the response
res.statusCode = 200;
res.end(html);
// Don't proceed to other middleware
return;
}
// Continue to next middleware for non-index requests
next();
};
}
module.exports = templateHandlerMiddleware;