import compression from "compression"; import express, {Express, Router} from "express"; import {Server} from "http"; import ApplicationComponent from "../ApplicationComponent.js"; import {logger, preventContextCorruptionMiddleware} from "../Logger.js"; import Middleware from "../Middleware.js"; import {Type} from "../Utils.js"; export default class ExpressAppComponent extends ApplicationComponent { private readonly addr: string; private readonly port: number; private server?: Server; private expressApp?: Express; public constructor(addr: string, port: number) { super(); this.addr = addr; this.port = port; } public async start(app: Express): Promise { this.server = app.listen(this.port, this.addr, () => { logger.info(`Web server running on http://${this.addr}:${this.port}`); }); // Proxy app.set('trust proxy', 'loopback'); this.expressApp = app; } public async initRoutes(router: Router): Promise { router.use(preventContextCorruptionMiddleware(express.json({ type: req => req.headers['content-type']?.match(/^application\/(.+\+)?json$/), }))); router.use(preventContextCorruptionMiddleware(express.urlencoded({ extended: true, }))); // gzip router.use(compression()); router.use((req, res, next) => { req.middlewares = []; req.as = (type: Type): M => { const middleware = req.middlewares.find(m => m.constructor === type); if (!middleware) throw new Error('Middleware ' + type.name + ' not present in this request.'); return middleware as M; }; res.formatViewData = function ( viewName: string, data?: Record, callback?: (err: Error, html: string) => void, ) { this.format({ html: () => { this.render(viewName, data, callback); }, json: () => { if (typeof data === 'undefined') data = {}; const serialized = JSON.stringify({...data, viewName}, (key, value) => { if (key.startsWith('_') || typeof value === 'function') return undefined; else return value; }); this.contentType('application/json'); this.send(serialized); }, }); }; next(); }); } public async stop(): Promise { const server = this.server; if (server) { await this.close('Webserver', callback => server.close(callback)); } } public getServer(): Server { if (!this.server) throw 'Server was not initialized.'; return this.server; } public getExpressApp(): Express { if (!this.expressApp) throw new Error('Express app not initialized.'); return this.expressApp; } }