UNPKG

silvie

Version:

Typescript Back-end Framework

311 lines (305 loc) 12.5 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _http = _interopRequireDefault(require("http")); var _https = _interopRequireDefault(require("https")); var _spdy = _interopRequireDefault(require("spdy")); var _fs = _interopRequireDefault(require("fs")); var _path = _interopRequireDefault(require("path")); var _cors = _interopRequireDefault(require("cors")); var _multer = _interopRequireDefault(require("multer")); var _bodyParser = _interopRequireDefault(require("body-parser")); var _cookieParser = _interopRequireDefault(require("cookie-parser")); var _express = _interopRequireDefault(require("express")); var _middleware = require("../middleware"); var _expressSession = _interopRequireDefault(require("express-session")); var _uuid = require("uuid"); var _redis = _interopRequireDefault(require("redis")); var _connectRedis = _interopRequireDefault(require("connect-redis")); var _sessionFileStore = _interopRequireDefault(require("session-file-store")); var _log = _interopRequireDefault(require("../../utils/log")); function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; } function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; } function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; } function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } const config = process.configs.http; class HTTPServer { constructor() { _defineProperty(this, "app", void 0); _defineProperty(this, "srv", void 0); _defineProperty(this, "upload", void 0); _defineProperty(this, "globalMiddlewares", []); _defineProperty(this, "routes", []); } /** * Initialize a new HTTP Server */ init(instanceCallback) { let app = (0, _express.default)(); app.disable('x-powered-by'); if (config.trustProxy) { app.set('trust proxy', 1); } if (instanceCallback instanceof Function) { app = instanceCallback(app); } this.app = app; this.initCORS(); this.initBodyParser(); this.initCookie(); this.initSession(); this.initUploads(); this.initGlobalMiddlewares(); this.initStatics(); this.initRoutes(); this.initServer(); } initCORS() { if (config.cors.enabled) { this.app.use((0, _cors.default)({ origin: config.cors.originsAllowed, methods: config.cors.methodsAllowed, allowedHeaders: config.cors.headersAllowed, exposedHeaders: config.cors.headersAllowed, credentials: config.cors.allowCredentials, maxAge: config.cors.maxAge, preflightContinue: config.cors.continuePreflight, optionsSuccessStatus: config.cors.optionsSuccessStatus })); } } initBodyParser() { if (config.body.enabled && config.body.parsers instanceof Array) { config.body.parsers.forEach(parser => { if (parser.type === 'json') { var _parser$options; this.app.use(_bodyParser.default.json({ limit: parser.limit, inflate: parser.inflate, type: parser.mime, strict: ((_parser$options = parser.options) === null || _parser$options === void 0 ? void 0 : _parser$options.strict) || false })); } if (parser.type === 'urlencoded') { var _parser$options2, _parser$options3; this.app.use(_bodyParser.default.urlencoded({ inflate: parser.inflate, limit: parser.limit, type: parser.mime, extended: ((_parser$options2 = parser.options) === null || _parser$options2 === void 0 ? void 0 : _parser$options2.extended) || false, parameterLimit: ((_parser$options3 = parser.options) === null || _parser$options3 === void 0 ? void 0 : _parser$options3.parameterLimit) || 1000 })); } if (parser.type === 'text') { var _parser$options4; this.app.use(_bodyParser.default.text({ inflate: parser.inflate, limit: parser.limit, type: parser.mime, defaultCharset: (_parser$options4 = parser.options) === null || _parser$options4 === void 0 ? void 0 : _parser$options4.defaultCharset })); } if (parser.type === 'raw') { this.app.use(_bodyParser.default.raw({ inflate: parser.inflate, limit: parser.limit, type: parser.mime })); } }); } } initSession() { if (config.session.enabled) { if (config.cookie.enabled && config.cookie.secret !== config.session.secret) { throw new Error('Cookie and Session secrets do not match'); } let store; if (config.session.driver === 'file') { const FileStore = (0, _sessionFileStore.default)(_expressSession.default); store = new FileStore({ path: _path.default.resolve(process.rootPath, `.silvie/${config.session.driverOptions.file.path}`), extension: config.session.driverOptions.file.extension, ttl: config.session.driverOptions.file.ttl }); } else if (config.session.driver === 'redis') { const RedisStore = (0, _connectRedis.default)(_expressSession.default); const redisClient = _redis.default.createClient(); store = new RedisStore({ client: redisClient, host: config.session.driverOptions.redis.host || process.env.REDIS_HOST, port: config.session.driverOptions.redis.port || process.env.REDIS_PORT, password: config.session.driverOptions.redis.password || process.env.REDIS_PASSWORD, ttl: config.session.driverOptions.redis.ttl, prefix: config.session.driverOptions.redis.prefix }); } else { throw new Error(`Invalid session driver '${config.session.driver}'`); } this.app.use((0, _expressSession.default)({ genid: () => (0, _uuid.v4)(), secret: config.session.secret || process.env.APP_KEY, resave: config.session.reSave, saveUninitialized: config.session.saveUninitialized, unset: config.session.unsetAction, trustProxy: config.session.trustProxy, store, name: config.session.cookie.name })); } } initCookie() { if (config.cookie.enabled) { if (config.session.enabled && config.session.secret !== config.cookie.secret) { throw new Error('Cookie and Session secrets do not match'); } this.app.use((0, _cookieParser.default)(config.cookie.secret || process.env.APP_KEY)); } } initUploads() { if (config.uploads.enabled) { this.upload = (0, _multer.default)({ dest: _path.default.resolve(process.rootPath, `.silvie/${config.uploads.tempDirectory}`), limits: { fieldSize: config.uploads.maxFileSize } }); } } initStatics() { config.statics.forEach(statics => { var _statics$alias; this.app.use((_statics$alias = statics.alias) !== null && _statics$alias !== void 0 ? _statics$alias : '/', _express.default.static(_path.default.resolve(process.rootPath, statics.path), { cacheControl: statics.options.cacheControl, dotfiles: statics.options.dotfiles, etag: statics.options.etag, extensions: statics.options.extensions, immutable: statics.options.immutable, index: statics.options.index, lastModified: statics.options.lastModified, maxAge: statics.options.maxAge, redirect: statics.options.redirect })); }); } initGlobalMiddlewares() { this.globalMiddlewares.forEach(middlewareName => { if (middlewareName in _middleware.middlewares) { this.app.use(_middleware.middlewares[middlewareName]); } else { throw new Error(`Unknown global middleware '${middlewareName}'`); } }); } initRoutes() { this.routes.forEach(route => { const middlewareHandlers = route.middlewares.map(middlewareName => { if (middlewareName in _middleware.middlewares) { return _middleware.middlewares[middlewareName]; } throw new Error(`Used unknown middleware '${middlewareName}' for route '${route.method.toUpperCase()} ${route.url}'`); }); if (route.upload) { if (route.upload.action === 'block') { middlewareHandlers.push(this.upload.none()); } else if (route.upload.action === 'any') { middlewareHandlers.push(this.upload.any()); } else if (route.upload.action === 'multiple') { middlewareHandlers.push(this.upload.fields(route.upload.options)); } else if (route.upload.action === 'array') { middlewareHandlers.push(this.upload.array(route.upload.options.fieldName, route.upload.options.maxCount)); } else if (route.upload.action === 'single') { middlewareHandlers.push(this.upload.single(route.upload.options)); } else { throw new Error(`Invalid upload type '${route.upload.action}' for route '${route.method.toUpperCase()} ${route.url}'`); } } this.app[route.method](route.url, middlewareHandlers, route.handler); }); } initServer() { let server = null; if (config.HTTP2) { if (!config.ssl.enabled) { throw new Error('You have to enable SSL for HTTP/2'); } if (!config.ssl.keyFile || !_fs.default.existsSync(config.ssl.keyFile)) { throw new Error('Missing SSL Key file'); } if (!config.ssl.certFile || !_fs.default.existsSync(config.ssl.certFile)) { throw new Error('Missing SSL Cert file'); } server = _spdy.default.createServer({ key: _fs.default.readFileSync(config.ssl.keyFile), cert: _fs.default.readFileSync(config.ssl.certFile), passphrase: config.ssl.passphrase }, this.app); } else if (config.ssl.enabled) { if (!config.ssl.keyFile || !_fs.default.existsSync(config.ssl.keyFile)) { throw new Error('Missing SSL Key file'); } if (!config.ssl.certFile || !_fs.default.existsSync(config.ssl.certFile)) { throw new Error('Missing SSL Cert file'); } server = _https.default.createServer({ key: _fs.default.readFileSync(config.ssl.keyFile), cert: _fs.default.readFileSync(config.ssl.certFile), passphrase: config.ssl.passphrase }, this.app); } else { server = _http.default.createServer(this.app); } this.srv = server; } /** * Return express server instance */ get expressServer() { return this.app; } /** * Return HTTP server instance */ get server() { return this.srv; } /** * Registers a route handler with some middlewares * @param method HTTP Verb * @param url Route URL * @param routeMiddlewares Route middlewares array * @param upload Upload configuration * @param handler Route handler */ registerRoute(method, url, routeMiddlewares = [], upload = null, handler) { this.routes.push({ method, url, middlewares: routeMiddlewares, upload, handler }); } /** * Registers a middleware on the whole HTTP Server * @param middlewareName The name middleware to register */ globalMiddleware(middlewareName) { this.globalMiddlewares.push(middlewareName); } /** * Starts listening on a port in this order: --port, -p, .env.APP_PORT, config.port, customPort */ start(customPort = 5000, customHost = '0.0.0.0') { const port = process.args.port || process.args.p || process.env.APP_PORT || config.port || customPort; const host = process.args.host || process.args.h || process.env.APP_HOST || config.host || customHost; this.srv.listen(port, host, error => { if (error) _log.default.error('Server Start Failed', 'An error occurred'); _log.default.success('Server Started', `on http${config.HTTP2 || config.ssl.enabled ? 's' : ''}://${host}:${port}`); }); } } const server = new HTTPServer(); var _default = exports.default = server;