2020-04-22 15:52:17 +02:00
|
|
|
import ApplicationComponent from "../ApplicationComponent";
|
2020-07-11 11:46:16 +02:00
|
|
|
import express, {Express, Router} from "express";
|
2020-11-02 17:48:52 +01:00
|
|
|
import {log, makeUniqueLogger} from "../Logger";
|
2020-04-22 15:52:17 +02:00
|
|
|
import {Server} from "http";
|
2020-07-09 14:18:05 +02:00
|
|
|
import compression from "compression";
|
2020-09-25 22:03:22 +02:00
|
|
|
import Middleware from "../Middleware";
|
|
|
|
import {Type} from "../Utils";
|
2020-04-22 15:52:17 +02:00
|
|
|
|
2020-09-25 22:03:22 +02:00
|
|
|
export default class ExpressAppComponent extends ApplicationComponent {
|
2020-09-17 21:15:37 +02:00
|
|
|
private readonly addr: string;
|
2020-04-22 15:52:17 +02:00
|
|
|
private readonly port: number;
|
|
|
|
private server?: Server;
|
2020-08-05 12:05:52 +02:00
|
|
|
private expressApp?: Express;
|
2020-04-22 15:52:17 +02:00
|
|
|
|
2020-09-17 21:15:37 +02:00
|
|
|
public constructor(addr: string, port: number) {
|
2020-04-22 15:52:17 +02:00
|
|
|
super();
|
2020-09-17 21:15:37 +02:00
|
|
|
this.addr = addr;
|
2020-04-22 15:52:17 +02:00
|
|
|
this.port = port;
|
|
|
|
}
|
|
|
|
|
2020-07-11 11:46:16 +02:00
|
|
|
public async start(app: Express): Promise<void> {
|
2020-09-17 21:15:37 +02:00
|
|
|
this.server = app.listen(this.port, this.addr, () => {
|
2020-11-02 17:48:52 +01:00
|
|
|
log.info(`Web server running on ${this.addr}:${this.port}.`);
|
2020-04-22 15:52:17 +02:00
|
|
|
});
|
2020-07-15 12:35:14 +02:00
|
|
|
|
|
|
|
// Proxy
|
|
|
|
app.set('trust proxy', 'loopback');
|
2020-08-05 12:05:52 +02:00
|
|
|
|
|
|
|
this.expressApp = app;
|
2020-07-11 11:46:16 +02:00
|
|
|
}
|
2020-04-22 15:52:17 +02:00
|
|
|
|
2020-07-11 11:46:16 +02:00
|
|
|
public async init(router: Router): Promise<void> {
|
2020-08-28 17:40:04 +02:00
|
|
|
router.use(express.json({
|
2020-09-25 23:42:15 +02:00
|
|
|
type: req => req.headers['content-type']?.match(/^application\/(.+\+)?json$/),
|
2020-08-28 17:40:04 +02:00
|
|
|
}));
|
2020-06-14 15:08:56 +02:00
|
|
|
router.use(express.urlencoded({
|
|
|
|
extended: true,
|
|
|
|
}));
|
2020-04-22 15:52:17 +02:00
|
|
|
|
2020-07-09 14:18:05 +02:00
|
|
|
// gzip
|
|
|
|
router.use(compression());
|
|
|
|
|
2020-04-22 15:52:17 +02:00
|
|
|
router.use((req, res, next) => {
|
2020-11-02 17:48:52 +01:00
|
|
|
req.log = makeUniqueLogger();
|
2020-09-25 22:03:22 +02:00
|
|
|
req.middlewares = [];
|
2020-09-25 23:42:15 +02:00
|
|
|
req.as = <M extends Middleware>(type: Type<M>): M => {
|
2020-09-25 22:03:22 +02:00
|
|
|
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;
|
|
|
|
};
|
2020-04-22 15:52:17 +02:00
|
|
|
next();
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
public async stop(): Promise<void> {
|
2020-09-25 23:42:15 +02:00
|
|
|
const server = this.server;
|
|
|
|
if (server) {
|
|
|
|
await this.close('Webserver', callback => server.close(callback));
|
2020-04-22 15:52:17 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public getServer(): Server {
|
|
|
|
if (!this.server) throw 'Server was not initialized.';
|
|
|
|
return this.server;
|
|
|
|
}
|
2020-08-05 12:05:52 +02:00
|
|
|
|
|
|
|
public getExpressApp(): Express {
|
2020-09-25 23:42:15 +02:00
|
|
|
if (!this.expressApp) throw new Error('Express app not initialized.');
|
|
|
|
return this.expressApp;
|
2020-08-05 12:05:52 +02:00
|
|
|
}
|
2020-06-14 21:47:18 +02:00
|
|
|
}
|