imsdk-server-core
Version:
轻量级Web服务器框架、WebSocket服务器框架。采用Typescript编写,简单易用。
221 lines (220 loc) • 9.97 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.WebServer = void 0;
/**
* 对express及其常用插件封装的类
* express相关信息:https://github.com/expressjs/express
* helmet相关信息:https://github.com/helmetjs/helmet
* compression相关信息:https://github.com/expressjs/compression
* cookie-parser相关信息:https://github.com/expressjs/cookie-parser
* body-parser相关信息:https://github.com/expressjs/body-parser
* multer相关信息:https://github.com/expressjs/multer
*/
const express_1 = __importDefault(require("express"));
const helmet_1 = __importDefault(require("helmet"));
const compression_1 = __importDefault(require("compression"));
const cookie_parser_1 = __importDefault(require("cookie-parser"));
const body_parser_1 = __importDefault(require("body-parser"));
const multer_1 = __importDefault(require("multer"));
const uuid_1 = require("uuid");
const https_1 = __importDefault(require("https"));
const http_1 = __importDefault(require("http"));
class WebServer {
/**
* @param context 上下文包装类实例
* @param category 日志分类
* @param config 配置信息
*/
constructor(context, category, config = {}) {
this._context = context;
this._config = {
helmet: {},
compress: {},
cookieSecret: uuid_1.v1(),
cookieOptions: {},
bodyParserJson: {},
bodyParserForm: { extended: true },
uploadKey: null,
uploadDir: null,
uploadMimeTypes: { 'image/jpg': 'jpg', 'image/png': 'png', 'image/gif': 'gif', 'image/bmp': 'bmp' },
webRootUrl: '',
webSignPwd: null
};
Object.assign(this._config, config); //拷贝配置信息
//绑定log4js实例
this._logger = context.getLogger(category);
//绑定app和server
this._webapp = express_1.default(); //创建express应用实例
this._server = context.ssls ? https_1.default.createServer(context.readSSLKerCert(), this._webapp) : http_1.default.createServer(this._webapp); //创建HTTP/S服务器实例
//其它属性
this._upload = null; //文件上传处理实例
}
/**
* 加载比较常用的几个第三方模块
*/
loadBaseModules() {
//启用helmet插件
if (this._config.helmet) {
this._webapp.use(helmet_1.default(this.ensureObject(this._config.helmet)));
this._logger.info('helmet module was loaded');
}
//启用compress插件(放在最前面可以保证后面的所有内容都经过压缩)
if (this._config.compress) {
this._webapp.use(compression_1.default(this.ensureObject(this._config.compress)));
this._logger.info('compression module was loaded');
}
//启用cookie-parser插件
if (this._config.cookieSecret) {
this._webapp.use(cookie_parser_1.default(this._config.cookieSecret, this.ensureObject(this._config.cookieOptions)));
this._logger.info('cookie-parser module was loaded');
}
//启用cookie-parser插件,解析application/json
if (this._config.bodyParserJson) {
this._webapp.use(body_parser_1.default.json(this.ensureObject(this._config.bodyParserJson)));
this._logger.info('body-parser.json module was loaded');
}
//启用cookie-parser插件,解析application/x-www-form-urlencoded
if (this._config.bodyParserForm) {
this._webapp.use(body_parser_1.default.urlencoded(this.ensureObject(this._config.bodyParserForm)));
this._logger.info('body-parser.urlencoded module was loaded');
}
}
/**
* 加载打印全部请求信息的模块
* @param logHeaders 是否打印请求头信息
* @param logArgs 是否打印参数信息
*/
loadPrintModule(logHeaders = false, logArgs = false) {
this._webapp.all('*', (req, resp, next) => {
this._logger.info(this._context.getIPV4(req), req.originalUrl); //打印出所有请求路径
if (logHeaders)
this._logger.debug('req.headers ->', req.headers);
if (logArgs) {
if (!this._context.isEmptyObject(req.params))
this._logger.debug('req.params ->', req.params);
if (!this._context.isEmptyObject(req.body))
this._logger.debug('req.body ->', req.body);
if (!this._context.isEmptyObject(req.query))
this._logger.debug('req.query ->', req.query);
if (!this._context.isEmptyObject(req.cookies))
this._logger.debug('req.cookies ->', req.cookies);
if (!this._context.isEmptyObject(req.signedCookies))
this._logger.debug('req.signedCookies ->', req.signedCookies);
}
next();
});
this._logger.info('inner-print module was loaded');
}
/**
* 加载文件上传模块,具体属性参考依赖库 https://github.com/expressjs/multer
* @param url 上传请求的url
* @param cb 上传成功或失败的回调,第一个回调参数code=200为成功,其它为失败
* @param options 加载文件上传模块,具体属性参考依赖库 https://github.com/expressjs/multer
*/
loadUploadModule(url, cb, options = {}) {
if (!this._config.uploadKey || !this._config.uploadDir) {
throw Error('upload configuration not specified');
}
this._upload = multer_1.default({
storage: options.storage || multer_1.default.diskStorage({
destination: (req, file, callback) => {
const date = new Date();
const folder = this._config.uploadDir + '/' + date.getFullYear() + '_' + (date.getMonth() + 1) + '_' + date.getDate() + '/';
if (this._context.mkdirsSync(folder)) {
callback(null, folder);
}
else {
callback(new Error('创建文件夹出错'), undefined);
}
},
filename: (req, file, callback) => {
const suffix = this._config.uploadMimeTypes[file.mimetype.toLowerCase()];
if (suffix) {
callback(null, uuid_1.v1() + '.' + suffix);
}
else {
callback(new Error('不支持的文件格式'), undefined);
}
}
}),
dest: options.dest,
limits: options.limits || {
fileSize: 1024 * 1024 * 10
},
preservePath: options.preservePath,
fileFilter: options.fileFilter,
});
//实际使用时,必须为POST请求才能收到文件
this._webapp.all(url, (req, resp) => {
this._upload.single(this._config.uploadKey)(req, resp, (error) => {
if (req.file) {
this._logger.debug('req.file ->', req.file);
if (error) {
cb(500, 'Internal Server Error, ' + error.toString(), req, resp);
}
else {
const data = {};
Object.assign(data, req.body);
data._path = req.file.path.replace(new RegExp('\\\\', 'gm'), '/').replace(this._config.uploadDir, ''); //windows系统下分隔符为'\'
data._size = req.file.size;
data._mimetype = req.file.mimetype;
data._orgname = req.file.originalname;
this._logger.debug('success data ->', data);
cb(200, data, req, resp);
}
}
else {
cb(400, 'Bad Request, ' + (error ? error.toString() : new Error('没有收到文件').toString()), req, resp);
}
});
});
this._logger.info('inner-upload module was loaded');
}
/**
* 加载静态资源到express容器,具体属性参考依赖库 https://github.com/expressjs/express
* @param url http(s)访问请求路径
* @param path 文件或文件夹的路径
* @param options 配置信息,具体属性参考依赖库 https://github.com/expressjs/express
*/
loadStaticModule(url, path, options) {
this._webapp.use(url, express_1.default.static(path, options));
}
/**
* 开启服务器
* @param callback 服务器启动后的回调函数
*/
start(callback) {
this._server.listen(this._context.port, () => {
this._logger.info('ssls', this._context.ssls, this._context.host, this._context.port, 'is listening...');
if (callback)
callback();
});
}
/**
* 关闭服务器
* @param callback 服务器关闭后的回调函数
*/
close(callback) {
this._server.close((error) => {
this._logger.info('ssls', this._context.ssls, this._context.host, this._context.port, 'was closed.');
if (callback)
callback(error);
});
}
get logger() { return this._logger; }
get webapp() { return this._webapp; }
get server() { return this._server; }
get webRootUrl() { return this._config.webRootUrl; }
get webSignPwd() { return this._config.webSignPwd; }
/**
* 确保返回一个object类型
* @param config
*/
ensureObject(config) {
return config && typeof config === 'object' ? config : {};
}
}
exports.WebServer = WebServer;