UNPKG

web_plsql

Version:

The Express Middleware for Oracle PL/SQL

186 lines (153 loc) 5.52 kB
import debugModule from 'debug'; const debug = debugModule('webplsql:server'); import http from 'node:http'; import https from 'node:https'; import express from 'express'; import bodyParser from 'body-parser'; import cookieParser from 'cookie-parser'; import compression from 'compression'; import {z$configType} from './types.js'; import {installShutdown} from './shutdown.js'; import {writeAfterEraseLine} from './tty.js'; import {poolCreate, poolsClose} from '../src/oracle.js'; import {handlerUpload} from './handlerUpload.js'; import {handlerLogger} from './handlerLogger.js'; import {initMetrics, handlerMetrics} from './handlerMetrics.js'; import {handlerWebPlSql} from './handlerPlSql.js'; import {getPackageVersion, getExpressVersion} from './version.js'; import {readFileSyncUtf8, getJsonFile} from './file.js'; /** * @typedef {import('express').Express} Express * @typedef {import('express').Request} Request * @typedef {import('express').Response} Response * @typedef {import('express').NextFunction} NextFunction * @typedef {import('oracledb').Pool} Pool * @typedef {import('./types.js').environmentType} environmentType * @typedef {import('./types.js').configType} configType */ /** * Create HTTP server. * @param {Express} app - express application * @param {number} port - port number * @param {Pool[]} connectionPools - database connection * @returns {Promise<http.Server>} - server */ export const createHttpServer = (app, port, connectionPools) => { return new Promise((resolve) => { // Create server // eslint-disable-next-line @typescript-eslint/no-misused-promises const server = http.createServer({}, app); // Install shutdown handler installShutdown(async () => { // Close database pool. await poolsClose(connectionPools); // Close server return new Promise((resolve) => server.close(() => resolve())); }); // Listen on HTTP ports server.listen(port, () => { resolve(server); }); }); }; /** * Create HTTPS server. * @param {Express} app - express application * @param {string} sslKeyFilename - ssl * @param {string} sslCertFilename - ssl * @param {number} port - port number * @param {Pool[]} connectionPools - database connection * @returns {Promise<https.Server>} - server */ export const createHttpsServer = (app, sslKeyFilename, sslCertFilename, port, connectionPools) => { return new Promise((resolve) => { // Load certificates const key = readFileSyncUtf8(sslKeyFilename); const cert = readFileSyncUtf8(sslCertFilename); // Create server // eslint-disable-next-line @typescript-eslint/no-misused-promises const server = https.createServer({key, cert}, app); // Install shutdown handler installShutdown(async () => { // Close database pool. await poolsClose(connectionPools); // Close server return new Promise((resolve) => server.close(() => resolve())); }); // Listen on HTTP ports server.listen(port, () => { resolve(server); }); }); }; /** * Start HTTP server. * @param {configType} config - The config. * @returns {Promise<void>} - Promise. */ export const startHttpServer = async (config) => { debug('startHttpServer', config); const expressVersion = getExpressVersion(); const packageVersion = getPackageVersion(); config = z$configType.parse(config); console.log(`WEB_PL/SQL ${packageVersion} using express ${expressVersion}`); // Create express app const app = express(); // Metrics const metrics = initMetrics(); app.use(handlerMetrics(metrics)); // Serving static files for (const i of config.routeStatic) { app.use(i.route, express.static(i.directoryPath)); console.log(`Static resources on "${i.route}" from directory ${i.directoryPath}`); } // Default middleware app.use(handlerUpload()); app.use(bodyParser.json()); app.use(bodyParser.urlencoded({extended: true})); app.use(cookieParser()); app.use(compression()); // Access log if (config.loggerFilename.length > 0) { console.log(`Access log in "${config.loggerFilename}"`); app.use(handlerLogger(config.loggerFilename)); } /** @type {Pool[]} */ const connectionPools = []; // Oracle pl/sql express middleware for (const i of config.routePlSql) { // Allocate the Oracle database pool const pool = await poolCreate(i.user, i.password, i.connectString); connectionPools.push(pool); app.use([`${i.route}/:name`, i.route], handlerWebPlSql(pool, i)); console.log(`Application route "http://localhost:${config.port}${i.route}"`); console.log(` Oracle user: ${i.user}`); console.log(` Oracle server: ${i.connectString}`); console.log(` Oracle document table: ${i.documentTable}`); } // Update metrics every second if (config.monitorConsole) { setInterval(() => { // Update requests per second const requestsLastInterval = metrics.requestsInLastInterval; metrics.requestsInLastInterval = 0; // Clear console and display metrics writeAfterEraseLine(`Total requests: ${metrics.totalRequests}, requests per second: ${requestsLastInterval}`); }, 1000); } await createHttpServer(app, config.port, connectionPools); }; /** * Load configuration. * @param {string} [filename] - The configuration filename. * @returns {configType} - Promise. */ export const loadConfig = (filename) => { debug('loadConfig', filename); if (typeof filename !== 'string' || filename.length === 0) { filename = 'config.json'; } const data = getJsonFile(filename); const config = z$configType.parse(data); return config; };