UNPKG

cor-base-service

Version:

Library build upon COR web services. Handles authN/authZ, standarizes logging and error messages

121 lines (120 loc) 4.7 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.createExpressApp = void 0; const express_1 = __importDefault(require("express")); const http_1 = require("./auth/http"); const http_status_codes_1 = require("http-status-codes"); const pino_http_1 = require("pino-http"); const express_openapi_validator_1 = require("express-openapi-validator"); const fs_1 = require("fs"); const express_list_endpoints_1 = __importDefault(require("express-list-endpoints")); const buildIgnorePaths = (paths, version) => { const ignorePaths = []; ignorePaths.push("/healthcheck"); ignorePaths.push(...paths.map((path) => `/v${version}${path}`)); return ignorePaths; }; const getPinoHttp = (enabled, ignorePaths, logger) => { const options = { logger: logger, autoLogging: { ignore: (req) => { if (!enabled) { // ? true to ignore, hence false to autologging. return true; } else { if (req.url) { if (ignorePaths.includes(req.url)) { return true; } } return false; } } } }; return (0, pino_http_1.pinoHttp)(options); }; const getOpenAPIValidator = (logger, config) => { try { (0, fs_1.realpathSync)(config.path); } catch (err) { logger.error("OpenAPI spec file not found"); process.exit(1); } logger.info(`Using OpenAIP spec file: ${config.path}`); return (0, express_openapi_validator_1.middleware)({ apiSpec: config.path, validateRequests: config.validateRequests, validateResponses: config.validateResponses }); }; const get404Handler = () => { return (req, res) => { res.status(http_status_codes_1.StatusCodes.NOT_FOUND).json({ message: `URL not found: ${req.path}` }); }; }; // Express error handler const getErrorHandler = () => { return (err, req, res, next) => { const logger = req.app.get("logger"); // TODO: remove this logger when we are confident the handler handles all type of errors logger.warn({ error: err }, "Error handler middleware"); res.status(err.status || err.code || 500).json({ message: err.message, type: err.type, path: err.path }); next(); }; }; const printEndpoints = (app, logger) => { const endpoints = (0, express_list_endpoints_1.default)(app); for (const endpoint of endpoints) { logger.info({ methods: endpoint.methods, path: endpoint.path }); } }; const createExpressApp = (options, router, healthz = (_, res) => res.sendStatus(http_status_codes_1.StatusCodes.OK)) => { const app = (0, express_1.default)(); const { logger, config } = options; // Set helper settings app.set("logger", logger); app.set("config", config); // Content-Types app.use(express_1.default.json()); app.use(express_1.default.text()); // Set up and configure the logger const ignoreLogPaths = buildIgnorePaths(config.server.ignoreLogPaths ? config.server.ignoreLogPaths : [], config.apiVersion); logger.debug({ paths: ignoreLogPaths }, "Paths to not log requests from"); app.use(getPinoHttp(config.log.autoLogging, ignoreLogPaths, logger)); // Configure authentication const ignoreAuthPaths = buildIgnorePaths(config.server.ignoreAuthPaths ? config.server.ignoreAuthPaths : [], config.apiVersion); logger.debug({ paths: ignoreAuthPaths }, "Paths to not enforce authentication"); app.set("authentication", config.server.auth.enabled); if (config.server.auth.enabled) { app.use((0, http_1.authentication)(ignoreAuthPaths)); logger.info("Authentication enforced on all handlers"); } // OpenAPI if (config.openAPI.path && config.openAPI.path !== "") { app.use(getOpenAPIValidator(logger, config.openAPI)); } // Healthcheck endpoint app.get("/healthcheck", healthz); // Routes if (router) { const routerPath = router.path !== "" ? `/${router.path}` : ""; app.use(`${routerPath}`, router.getRouter()); // app.use(`/v${config.apiVersion}${routerPath}`, router.getRouter()); } // Error handlers app.use(get404Handler()); app.use(getErrorHandler()); // Log all the endpoints printEndpoints(app, logger); return app; }; exports.createExpressApp = createExpressApp;