UNPKG

nxkit

Version:

This is a collection of tools, independent of any other libraries

356 lines (355 loc) 10.9 kB
"use strict"; /* ***** BEGIN LICENSE BLOCK ***** * Distributed under the BSD license: * * Copyright (c) 2015, xuewen.chu * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of xuewen.chu nor the * names of its contributors may be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL xuewen.chu BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * ***** END LICENSE BLOCK ***** */ Object.defineProperty(exports, "__esModule", { value: true }); const util_1 = require("./util"); const router_1 = require("./router"); const event_1 = require("./event"); const http = require("http"); const fs = require("./fs"); const path = require("path"); const incoming_form_1 = require("./incoming_form"); var shared = null; var mimeTypes = {}; var default_root = [process.cwd()]; var default_temp = incoming_form_1.default.temp_dir; function read_mime(filename) { var data = fs.readFileSync(__dirname + '/' + filename) + ''; var ls = data.replace(/ *#.*\r?\n?/g, '').split(/\n/); for (var i = 0; i < ls.length; i++) { var item = ls[i].replace(/^\s|\s$|;\s*$/g, '') .replace(/\s+|\s*=\s*/, '*%*').split('*%*'); var key = item[0]; var value = item[1]; if (value) { var values = value.split(/\s+/); var len2 = values.length; for (var j = 0; j < len2; j++) { mimeTypes[values[j]] = key; } } } } read_mime('mime.types'); read_mime('mime+.types'); /** * @class Server */ class Server extends event_1.Notification { /** * 构造函数 * @constructor * @param {Object} opt (Optional) 配置项 */ constructor(config) { super(); this.m_ws_conversations = {}; this.m_isRun = false; this.m_host = ''; this.m_port = 0; // 自动端口 /** * 打印log */ this.printLog = !!util_1.default.config.moreLog; /** * session timeout default 15 minutes * @type {Number} */ this.session = 15; /** * @type {String} */ this.formHash = 'md5'; /** * 站点根目录 * @type {String} */ this.root = default_root; /** * 临时目录 * @type {String} */ this.temp = default_temp; /** * 站点虚拟目录 * @type {String} */ this.virtual = ''; /** * web socket conversation verify origins * @type {String[]} */ this.origins = ['*:*']; /** * @type {String} */ this.allowOrigin = '*'; /** * 是否浏览静态文件目录 * @type {Boolean} */ this.autoIndex = false; /** * 静态缓存文件过期时间,以分钟为单位,为默认为30天 * @type {Number} */ this.expires = 60 * 24 * 30; /** * 静态文件缓存,该值可减低硬盘静态文件读取次数,但需要消耗内存,单位(秒) * @type {Number} */ this.fileCacheTime = 10; /** * Download file size limit * @type {Number} */ this.maxFileSize = 5 * 1024 * 1024; /** * Max form data size limit */ this.maxFormDataSize = 5 * 1024 * 1024; /** * Upload file size limit * @type {Number} */ this.maxUploadFileSize = 5 * 1024 * 1024; /** * 文本文件编码,默认为utf-8 */ this.textEncoding = 'utf-8'; /** * 静态gzip文件格式 * defaults javascript|text|json|xml * @type {Regexp} */ this.gzip = /javascript|text|json|xml/i; /** * 是否动态数据内容压缩 * @type {Boolean} */ this.agzip = true; /** * 默认页 * @type {String[]} */ this.defaults = ['index.html', 'index.htm', 'default.html']; /** * 设置禁止访问的目录 * @type {RegExp} */ this.disable = /^\/server/i; /** * 错误状态页 * @type {Object} */ this.errorStatus = {}; /** * 配置的文件mime * mime types * @type {Object} */ this.mimeTypes = mimeTypes; this.onWSConversationOpen = new event_1.EventNoticer('WSConversationOpen', this); this.onWSConversationClose = new event_1.EventNoticer('WSConversationClose', this); this.m_server = new http.Server(); this.router = new router_1.Router(); this.m_server.__wrap__ = this; config = config || {}; util_1.default.update(this, util_1.default.filter(config, [ 'printLog', 'autoIndex', 'mimeTypes', 'errorStatus', 'agzip', 'origins', 'allowOrigin', 'fileCacheTime', 'expires', 'timeout', 'session', 'maxFileSize', 'maxFormDataSize', 'maxUploadFileSize', 'textEncoding', 'defaults', 'formHash', ])); this.m_port = Number(process.env.WEB_SERVER_PORT) || Number(config.port) || 0; this.m_host = config.host ? String(config.host) : ''; this.root = config.root ? Array.isArray(config.root) ? config.root.map(e => path.resolve(e)) : [path.resolve(config.root)] : this.root; this.temp = config.temp ? path.resolve(config.temp) : this.temp; var disable = config.disable; if (disable) { if (Array.isArray(disable)) disable = disable.join(' '); disable = String(disable).trim().replace(/\s+/mg, '|'); this.disable = new RegExp('^\\/(' + disable + ')'); } if (config.virtual) { this.virtual = String(config.virtual).trim().replace(/^(\/|\\)*([^\/\\]+)/, '/$2'); } if ('gzip' in config) { if (config.gzip === false) { this.gzip = false; } else if (config.gzip instanceof RegExp) { this.gzip = config.gzip; } else { var gzip = String(config.gzip).trim().replace(/\s+/, '|'); this.gzip = new RegExp('javascript|text|json|xml|' + gzip, 'i'); } } fs.mkdirpSync(this.temp); this.router.config({ staticService: config.staticService, virtual: this.virtual, router: config.router, }); this.onWSConversationOpen.on(e => { var conv = e.data; this.m_ws_conversations[conv.token] = conv; // TODO private visit }); this.onWSConversationClose.on(e => { var conv = e.data; delete this.m_ws_conversations[conv.token]; // TODO private visit }); this.initializ(this.m_server); } get host() { return this.m_host; } get port() { return this.m_port; } /** * 请求超时时间(毫秒) * @type {Number} */ get timeout() { return this.m_server.timeout; } /** * @get impl */ get impl() { return this.m_server; } /** * Get wsConversations conversation */ get wsConversations() { return Object.create(this.m_ws_conversations); } set timeout(timeout) { timeout = Number(timeout) || this.m_server.timeout; this.m_server.setTimeout(timeout); } /** * @func interceptRequest(req, res) */ interceptRequest(req, res) { return false; } /** * MIME 获取类型 * @param {String} ename 扩展名或文件名称 * @return {String} */ getMime(name) { var mat = name.match(/\.([^$\?\/\\\.]+)((#|\?).+)?$/); if (mat) { name = mat[1]; } name = name.toLowerCase(); return this.mimeTypes[name] || mimeTypes[name] || 'application/octet-stream'; } /** * 是否正在运行 */ get isRun() { return this.m_isRun; } /** * 启动服务 */ start() { var complete = () => { var addr = (this.m_server).address(); this.m_host = addr.address; this.m_port = addr.port; this.m_isRun = true; this.trigger('Startup', {}); }; if (this.m_port) { this.m_server.listen(this.m_port, this.m_host, complete); } else if (this.m_host) { this.m_server.listen(String(this.m_host), complete); } else { this.m_server.listen(complete); } } /** * @func stop() sopt service */ stop() { this.m_server.close(); } /** * @func restart() restart service */ restart() { this.stop(); (async () => { var i = 4; while (--i) { if (!this.m_isRun) { this.start(); break; } await util_1.default.sleep(5e2 /*500ms*/); } })().catch(console.error); } } exports.Server = Server; exports.default = { /** * @func setShared */ setShared: function (server) { shared = server; }, /** * @get shared # default web server */ get shared() { return shared; }, };