import { WebConfig } from "./config"; import * as express from "express"; import { Express } from "express"; import Logging from "@hibas123/nodelogging"; import * as bodyparser from "body-parser"; import * as cookieparser from "cookie-parser"; import * as i18n from "i18n"; import * as compression from "compression"; import ApiRouter from "./api"; import ViewRouter from "./views/views"; import RequestError, { HttpStatusCode } from "./helper/request_error"; export default class Web { server: Express; private port: number; constructor(config: WebConfig) { this.server = express(); this.port = Number(config.port); this.registerMiddleware(); this.registerEndpoints(); this.registerErrorHandler(); } listen() { this.server.listen(this.port, () => { Logging.log(`Server listening on port ${this.port}`); }); } private registerMiddleware() { this.server.use(cookieparser()); this.server.use( bodyparser.json(), bodyparser.urlencoded({ extended: true }) ); this.server.use(i18n.init); //Logging Middleware this.server.use((req, res, next) => { let start = process.hrtime(); let finished = false; let to = false; let listener = () => { if (finished) return; finished = true; let td = process.hrtime(start); let time = !to ? (td[0] * 1e3 + td[1] / 1e6).toFixed(2) : "--.--"; let resColor = ""; if (res.statusCode >= 200 && res.statusCode < 300) resColor = "\x1b[32m"; //Green else if (res.statusCode === 304 || res.statusCode === 302) resColor = "\x1b[33m"; else if (res.statusCode >= 400 && res.statusCode < 500) resColor = "\x1b[36m"; //Cyan else if (res.statusCode >= 500 && res.statusCode < 600) resColor = "\x1b[31m"; //Red let m = req.method; while (m.length < 4) m += " "; Logging.log( `${m} ${req.originalUrl} ${ (req as any).language || "" } ${resColor}${res.statusCode}\x1b[0m - ${time}ms` ); res.removeListener("finish", listener); }; res.on("finish", listener); setTimeout(() => { to = true; listener(); }, 2000); next(); }); this.server.use( compression({ filter: (req, res) => { if (req.headers["x-no-compression"]) { return false; } return compression.filter(req, res); }, }) ); } private registerEndpoints() { this.server.use("/api", ApiRouter); this.server.use("/", ViewRouter); } private registerErrorHandler() { this.server.use((error, req: express.Request, res, next) => { if (!(error instanceof RequestError)) { error = new RequestError( error.message, error.status || HttpStatusCode.INTERNAL_SERVER_ERROR, error.nolog || false ); } if (error.status === 500 && !(error).nolog) { Logging.error(error); } else { Logging.log("Responded with Error", error.status); } if (req.accepts(["json"])) { res.json_status = error.status || 500; res.json({ error: error.message, status: error.status || 500, additional: error.additional, }); } else res.status(error.status || 500).send(error.message); }); } }