UNPKG

thinknode

Version:

A fast, flexible and all-in-one web framework for node.js.

356 lines (309 loc) 11 kB
'use strict'; exports.__esModule = true; var _promise = require('babel-runtime/core-js/promise'); var _promise2 = _interopRequireDefault(_promise); var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck'); var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn'); var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2); var _inherits2 = require('babel-runtime/helpers/inherits'); var _inherits3 = _interopRequireDefault(_inherits2); var _cluster = require('cluster'); var _cluster2 = _interopRequireDefault(_cluster); var _os = require('os'); var _os2 = _interopRequireDefault(_os); var _http2 = require('http'); var _http3 = _interopRequireDefault(_http2); var _Base = require('../Base'); var _Base2 = _interopRequireDefault(_Base); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } /** * remove / start or end of pathname * @return {} [] */ /** * * @author richen * @copyright Copyright (c) 2015 - <richenlin(at)gmail.com> * @license MIT * @version 15/11/26 */ var cleanPathname = function cleanPathname(pathname) { if (pathname === '/') { return ''; } if (pathname[0] === '/') { pathname = pathname.slice(1); } if (pathname.slice(-1) === '/') { pathname = pathname.slice(0, -1); } return pathname; }; /** * 小驼峰命名正则转换 * @type {RegExp} */ var sCamelReg = function sCamelReg(str) { var re = /_(\w)/g; return str.replace(re, function (all, letter) { return letter.toUpperCase(); }); }; /** * 大驼峰命名正则转换 * @type {RegExp} */ var bCamelReg = function bCamelReg(str) { var re = /_(\w)/g; var rstr = str.slice(1).replace(re, function (all, letter) { return letter.toUpperCase(); }); return str[0].toUpperCase() + rstr; }; /** * 检测Group,Controller和Action是否合法 * @type {RegExp} */ var nameReg = function nameReg(str) { if (/^[A-Za-z\_0-9]\w*$/.test(str)) { return true; } return false; }; /** * 解析pathname获取group * @param group * @param defaultValue * @returns {*} */ var parseGroup = function parseGroup(group) { var defaultValue = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'Home'; if (!group) { return defaultValue; } else if (!nameReg(group)) { return null; } return bCamelReg(group); }; /** * 解析pathname获取controller * @param controller * @param defaultValue * @returns {*} */ var parseController = function parseController(controller) { var defaultValue = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'Index'; if (!controller) { return defaultValue; } else if (!nameReg(controller)) { return null; } return bCamelReg(controller); }; /** * 解析pathname获取action * @param action * @param defaultValue * @returns {*} */ var parseAction = function parseAction(action) { var defaultValue = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'Index'; if (!action) { return defaultValue; } else if (!nameReg(action)) { return null; } return sCamelReg(action); }; var _class = function (_base) { (0, _inherits3.default)(_class, _base); function _class() { (0, _classCallCheck3.default)(this, _class); return (0, _possibleConstructorReturn3.default)(this, _base.apply(this, arguments)); } /* eslint-disable consistent-return */ _class.run = function run() { var clusterNums = THINK.config('use_cluster'); //不使用cluster if (!clusterNums) { return this.createServer(); } else { //使用cpu的个数 if (clusterNums === true) { clusterNums = _os2.default.cpus().length; } if (_cluster2.default.isMaster) { for (var i = 0; i < clusterNums; i++) { _cluster2.default.fork(); } _cluster2.default.on('exit', function (worker) { THINK.log(new Error('worker ' + worker.process.pid + ' died')); process.nextTick(function () { return _cluster2.default.fork(); }); }); } else { this.createServer(); } } }; /** * 创建HTTP服务 */ _class.createServer = function createServer() { var server = _http3.default.createServer(function (req, res) { var _http = void 0; return THINK.Http.run(req, res).then(function (data) { _http = data; var app = new THINK.App(); return app.exec(_http); }).then(function () { return THINK.statusAction(_http, 200); }).catch(function (err) { return THINK.statusAction(_http, _http._status || 500, err); }); }); //invoke bootstrap middleware return THINK.run('bootstrap', { server: server, app: new this() }).then(function () { //listening var host = THINK.config('app_host'); var port = THINK.config('app_port'); if (host) { server.listen(port, host); } else { server.listen(port); } THINK.log('====================================', 'THINK'); THINK.log('Server running at http://' + (host || '127.0.0.1') + ':' + port + '/', 'THINK'); THINK.log('Node.js Version: ' + process.version, 'THINK'); THINK.log('ThinkNode Version: ' + THINK.THINK_VERSION, 'THINK'); THINK.log('App Cluster Status: ' + (THINK.config('use_cluster') ? 'open' : 'closed'), 'THINK'); THINK.log('App File Auto Reload: ' + (THINK.APP_DEBUG ? 'open' : 'closed'), 'THINK'); THINK.log('App Enviroment: ' + (THINK.APP_DEBUG ? 'debug mode' : 'stand mode'), 'THINK'); THINK.log('====================================', 'THINK'); THINK.APP_DEBUG && THINK.log('Debugging mode is running, if the production environment, please modify the APP_DEBUG value to false', 'WARNING'); }); }; /** * * @param _http * @return {*} */ _class.prototype.exec = function exec(_http) { var _this2 = this; //禁止远程直接用带端口的访问,websocket下允许 if (THINK.config('use_proxy')) { if (_http.host !== _http.hostname && !_http.isWebSocket) { return THINK.statusAction(_http, 403); } } _http = this.getController(_http); //app begin return THINK.run('app_begin', _http).then(function () { process.nextTick(function () { //app end THINK.run('app_end', _http); }); return _this2.execController(_http); }); }; /** * 根据pathname解析定位分组/控制器/方法,及其他/格式参数 * @param _http * @param pathname * @return {*} */ _class.prototype.getController = function getController(_http, pathname) { if (pathname || !_http.group) { pathname = cleanPathname(pathname || _http.pathname); //去除pathname后缀 var suffix = THINK.config('url_pathname_suffix'); if (suffix && pathname.slice(0 - suffix.length) === suffix) { pathname = pathname.slice(0, pathname.length - suffix.length); } var paths = _http.splitPathName(pathname); var group = void 0, groupList = THINK.config('app_group_list'); if (groupList.length && paths[0] && groupList.indexOf(paths[0].toLowerCase()) > -1) { group = paths.shift(); } var controller = paths.shift(); var action = paths.shift(); //解析剩余path的参数 if (paths.length) { for (var i = 0, length = Math.ceil(paths.length) / 2; i < length; i++) { _http._get[paths[i * 2]] = paths[i * 2 + 1] || ''; } } _http.group = parseGroup(group, THINK.config('default_group')); _http.controller = parseController(controller, THINK.config('default_controller')); _http.action = parseAction(action, THINK.config('default_action')); } return _http; }; /** * 执行controller * @param _http * @return {Promise.<*>} */ _class.prototype.execController = function execController(_http) { //_http对象的group或controller不存在直接返回 if (!_http.group || !_http.controller) { return THINK.statusAction(_http, 404, 'Controller not found.'); } //controller instance var controller = void 0; try { var instance = THINK.controller(_http.group + '/' + _http.controller); controller = new instance(_http); } catch (e) { return THINK.statusAction(_http, 404, 'Controller ' + _http.group + '/' + _http.controller + ' not found.'); } return this.execAction(_http, controller); }; /** * 执行action * @param _http * @param controller * @return {Promise.<*>} */ _class.prototype.execAction = function execAction(_http, controller) { var suffix = _http.actionSuffix === '' ? '' : 'Action'; var act = '' + _http.action + suffix; var call = '__empty'; var flag = false; //action不存在时执行空方法 if (!controller[act]) { if (call && controller[call]) { flag = true; act = call; } } //action不存在 if (!controller[act] && !flag) { return THINK.statusAction(_http, 404, 'action ' + (_http.action || '') + ' not found.'); } //action前置操作 var commonBefore = '__before'; var before = '_before_'; var promises = _promise2.default.resolve(); //公共action前置操作 if (commonBefore && controller[commonBefore]) { promises = promises.then(function () { return controller[commonBefore](); }); } //当前action前置操作 if (before && controller['' + before + _http.action]) { promises = promises.then(function () { return controller['' + before + _http.action](); }); } return promises.then(function () { return controller[act](); }); }; return _class; }(_Base2.default); exports.default = _class;