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 { BADHINTS } from "dns"; import ApiRouter from "./api/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.language} ${resColor}${res.statusCode}\x1b[0m - ${time}ms`) res.removeListener("finish", listener) } res.on("finish", listener) setTimeout(() => { to = true; listener(); }, 2000) next() }) function shouldCompress(req, res) { if (req.headers['x-no-compression']) { // don't compress responses with this request header return false } // fallback to standard filter function return compression.filter(req, res) } this.server.use(compression({ filter: shouldCompress })) } 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)) { Logging.error(error); error = new RequestError(error.message, HttpStatusCode.INTERNAL_SERVER_ERROR); } else if (error.status === 500 && !(error).nolog) { Logging.error(error); } else { Logging.log(typeof error.message === "string" ? error.message.split("\n", 1)[0] : error.message); } if (req.accepts(["json"])) { res.json_status = error.status || 500; res.json({ error: error.message, status: error.status || 500 }) } else res.status(error.status || 500).send(error.message) }) } }