import * as plugins from './rendertron.plugins.js'; import * as paths from './rendertron.paths.js'; import { logger } from './rendertron.logging.js'; import { PrerenderResult } from './rendertron.classes.prerenderresult.js'; import { PrerenderManager } from './rendertron.classes.prerendermanager.js'; import { TaskManager } from './rendertron.taskmanager.js'; export class Rendertron { public projectinfo: plugins.projectinfo.ProjectInfo; public serviceServerInstance: plugins.typedserver.utilityservers.UtilityServiceServer; public prerenderManager: PrerenderManager; public taskManager: TaskManager; /** * starts the financeflow instance */ public async start() { this.projectinfo = new plugins.projectinfo.ProjectInfo(paths.packageDir); this.prerenderManager = new PrerenderManager(); this.taskManager = new TaskManager(this); await this.prerenderManager.start(); await this.taskManager.start(); this.serviceServerInstance = new plugins.typedserver.utilityservers.UtilityServiceServer({ serviceDomain: 'rendertron.lossless.one', serviceName: 'rendertron', serviceVersion: this.projectinfo.npm.version, addCustomRoutes: async (serverArg) => { serverArg.addRoute( '/render/*', new plugins.typedserver.servertools.Handler('GET', async (req, res) => { const requestedUrl = req.url.replace('/render/', ''); logger.log('info', `Got SSR request for ${requestedUrl}`); if (requestedUrl.startsWith('https://url(')) { logger.log('warn', `relative url error for ${requestedUrl}`); res.status(500); res.write('error due to relative protocol'); res.end(); return; } const originResponse = await plugins.smartrequest .request( requestedUrl, { method: 'GET', keepAlive: false, // headers: req.headers, }, true ) .catch((error) => { logger.log('warn', `the origin request errored for ${requestedUrl}`); res.write(`rendertron encountered an error for ${requestedUrl}`); res.end(); }); if (!originResponse) { return; } for (const header of Object.keys(originResponse.headers)) { res.setHeader(header, originResponse.headers[header]); } if (originResponse.headers['content-type']?.includes('text/html')) { logger.log('info', `Piping ${requestedUrl} through smartssr.`); res.write(await this.prerenderManager.getPrerenderResultForUrl(requestedUrl)); res.end(); } else { logger.log('info', `Serving ${requestedUrl} directly.`); for (const headerKey of Object.keys(originResponse.headers)) { console.log(`${headerKey}: ${originResponse.headers[headerKey]}`); res.set(headerKey, originResponse.headers[headerKey]); } originResponse.on('data', (data) => { res.write(data); }); originResponse.on('end', () => { res.end(); }); } }) ); }, }); await this.serviceServerInstance.start(); } public async stop() { this.serviceServerInstance ? await this.serviceServerInstance.stop() : null; this.prerenderManager ? await this.prerenderManager.stop() : null; this.taskManager ? await this.taskManager.stop() : null; } }