2025-01-01 07:33:33 +01:00
|
|
|
import * as plugins from './rendertron.plugins.js';
|
|
|
|
|
import * as paths from './rendertron.paths.js';
|
|
|
|
|
import { logger } from './rendertron.logging.js';
|
2026-04-29 13:53:20 +00:00
|
|
|
import { db } from './rendertron.db.js';
|
2025-01-01 07:33:33 +01:00
|
|
|
import { PrerenderResult } from './rendertron.classes.prerenderresult.js';
|
|
|
|
|
import { PrerenderManager } from './rendertron.classes.prerendermanager.js';
|
|
|
|
|
import { TaskManager } from './rendertron.taskmanager.js';
|
|
|
|
|
|
|
|
|
|
export class Rendertron {
|
2026-04-29 13:53:20 +00:00
|
|
|
public projectinfo!: plugins.projectinfo.ProjectInfo;
|
|
|
|
|
public serviceServerInstance!: plugins.typedserver.utilityservers.UtilityServiceServer;
|
|
|
|
|
public prerenderManager!: PrerenderManager;
|
|
|
|
|
public taskManager!: TaskManager;
|
2025-01-01 07:33:33 +01:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* starts the financeflow instance
|
|
|
|
|
*/
|
|
|
|
|
public async start() {
|
2026-04-29 13:53:20 +00:00
|
|
|
this.projectinfo = await plugins.projectinfo.ProjectInfo.create(paths.packageDir);
|
|
|
|
|
await db.init();
|
2025-01-01 07:33:33 +01:00
|
|
|
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/*',
|
2026-04-29 13:53:20 +00:00
|
|
|
'GET',
|
|
|
|
|
async (ctxArg) => {
|
|
|
|
|
const requestedUrl = `${ctxArg.url.pathname.replace('/render/', '')}${ctxArg.url.search}`;
|
2025-01-01 07:33:33 +01:00
|
|
|
logger.log('info', `Got SSR request for ${requestedUrl}`);
|
|
|
|
|
if (requestedUrl.startsWith('https://url(')) {
|
|
|
|
|
logger.log('warn', `relative url error for ${requestedUrl}`);
|
2026-04-29 13:53:20 +00:00
|
|
|
return new Response('error due to relative protocol', { status: 500 });
|
2025-01-01 07:33:33 +01:00
|
|
|
}
|
2026-04-29 13:53:20 +00:00
|
|
|
const originResponse = await plugins.smartrequest.SmartRequest.create()
|
|
|
|
|
.url(requestedUrl)
|
|
|
|
|
.options({ keepAlive: false })
|
|
|
|
|
.get()
|
2025-01-01 07:33:33 +01:00
|
|
|
.catch((error) => {
|
|
|
|
|
logger.log('warn', `the origin request errored for ${requestedUrl}`);
|
2026-04-29 13:53:20 +00:00
|
|
|
return null;
|
2025-01-01 07:33:33 +01:00
|
|
|
});
|
|
|
|
|
if (!originResponse) {
|
2026-04-29 13:53:20 +00:00
|
|
|
return new Response(`rendertron encountered an error for ${requestedUrl}`, { status: 502 });
|
2025-01-01 07:33:33 +01:00
|
|
|
}
|
2026-04-29 13:53:20 +00:00
|
|
|
const responseHeaders = new Headers();
|
|
|
|
|
for (const [headerKey, headerValue] of Object.entries(originResponse.headers)) {
|
|
|
|
|
if (Array.isArray(headerValue)) {
|
|
|
|
|
for (const headerValueItem of headerValue) {
|
|
|
|
|
responseHeaders.append(headerKey, headerValueItem);
|
|
|
|
|
}
|
|
|
|
|
} else if (headerValue !== undefined) {
|
|
|
|
|
responseHeaders.set(headerKey, headerValue.toString());
|
|
|
|
|
}
|
2025-01-01 07:33:33 +01:00
|
|
|
}
|
|
|
|
|
if (originResponse.headers['content-type']?.includes('text/html')) {
|
|
|
|
|
logger.log('info', `Piping ${requestedUrl} through smartssr.`);
|
2026-04-29 13:53:20 +00:00
|
|
|
return new Response(await this.prerenderManager.getPrerenderResultForUrl(requestedUrl), {
|
|
|
|
|
status: originResponse.status,
|
|
|
|
|
headers: responseHeaders,
|
|
|
|
|
});
|
2025-01-01 07:33:33 +01:00
|
|
|
} else {
|
|
|
|
|
logger.log('info', `Serving ${requestedUrl} directly.`);
|
2026-04-29 13:53:20 +00:00
|
|
|
return new Response(await originResponse.arrayBuffer(), {
|
|
|
|
|
status: originResponse.status,
|
|
|
|
|
headers: responseHeaders,
|
2025-01-01 07:33:33 +01:00
|
|
|
});
|
|
|
|
|
}
|
2026-04-29 13:53:20 +00:00
|
|
|
}
|
2025-01-01 07:33:33 +01:00
|
|
|
);
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
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;
|
2026-04-29 13:53:20 +00:00
|
|
|
if (db.status === 'connected') {
|
|
|
|
|
await db.close();
|
|
|
|
|
}
|
2025-01-01 07:33:33 +01:00
|
|
|
}
|
|
|
|
|
}
|