From 38ad516e082852b2f6e419c8238130cfceda87f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AE=87=E5=A4=A9?= Date: Tue, 22 Sep 2020 19:58:29 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E4=B8=AD=E9=97=B4=E4=BB=B6/?= =?UTF-8?q?=E8=B7=AF=E7=94=B1/=E8=B7=A8=E5=9F=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- index.js | 61 +++++++++++++++------------------------ lib/reg-init.js | 33 +++++++++++---------- middleware/credentials.js | 21 +++++++------- middleware/router.js | 52 +++++++++++++++++---------------- 4 files changed, 80 insertions(+), 87 deletions(-) diff --git a/index.js b/index.js index 8900156..259e328 100644 --- a/index.js +++ b/index.js @@ -36,9 +36,8 @@ function hideProperty(host, name, value) { export default class Five { constructor() { hideProperty(this, '__FIVE__', Object.assign({}, init)) - hideProperty(this, '__MODULES__', { __error__: null }) + hideProperty(this, '__MODULES__', {}) hideProperty(this, '__MIDDLEWARE__', []) - hideProperty(this, '__INSTANCE__', {}) } __init__() { @@ -94,63 +93,51 @@ export default class Five { // 获取全局配置 get(key) { - try { - return new Function('o', `return o.${key}`)(this.__FIVE__) - } catch (err) {} + return this.__FIVE__[key] } - // 加载中间件/缓存模块 + // 加载中间件 // 与别的中间件用法有些不一样, 回调的传入参数中的req和res, // 并非原生的request对象和response对象, // 而是框架内部封装过的,可通过origin属性访问原生的对象 - use(key, fn) { - if (arguments.length === 1) { - if (typeof key !== 'function') { - throw TypeError('argument 1 must be a callback') - } - this.__MIDDLEWARE__.push(key) - } else { - if (typeof key !== 'string') { - return - } - libs[key] = fn + use(fn) { + if (typeof fn === 'function') { + this.__MIDDLEWARE__.push(fn) + return this } + throw TypeError('argument must be a callback') } - // 预加载应用 + + // 预加载应用, 缓存以提高性能 preload(dir) { var list = fs.ls(dir) if (list) { - list.forEach(file => { - var { name } = path.parse(file) + list.forEach(item => { + var { name } = path.parse(item) if (name.startsWith('.')) { return } - try { - this.__MODULES__[name] = import(file) - } catch (err) { - this.__MODULES__.__error__ = err + // 如果是目录,则默认加载index.js, 其他文件不加载 + // 交由index.js自行处理, 用于复杂的应用 + if (fs.isdir(item)) { + item = path.join(item, './index.js') } + + this.__MODULES__[name] = import(item).catch(err => { + return { default: null } + }) }) } return this } - // 注册实例化对象到实例池中 + // 注入实例化对象到实例池中 // 与use方法不同的是, 这个会在server创建之前就已经执行 - ins(name, fn) { - var _this = this - if (arguments.length === 1) { - return this.__INSTANCE__[name] - } - if (typeof fn === 'function') { - fn.call(this, this.__FIVE__, function next(instance) { - if (instance) { - _this.__INSTANCE__[name] = instance - } - }) - } + install({ name, install }) { + this['$$' + name] = install.call(this, this.__FIVE__) + return this } // 启动http服务 diff --git a/lib/reg-init.js b/lib/reg-init.js index 2a8c0cf..b1c2c2f 100644 --- a/lib/reg-init.js +++ b/lib/reg-init.js @@ -1,11 +1,11 @@ /** - * - * @authors yutent (yutent@doui.cc) - * @date 2016-05-15 14:37:47 - * + * 部分配置 + * @author yutent + * @date 2020/09/22 17:19:39 */ -'use strict' +const ENV_PROD = 'production' +const ENV_DEV = 'development' export default { db: {}, @@ -24,27 +24,30 @@ export default { domain: '', // cookie域, 默认等于website port: 3000, routeMode: 'action', // action | __main__ - env: process.env.NODE_ENV === 'production' ? 'production' : 'development', - debug: process.env.NODE_ENV !== 'production', // debug模式 + env: process.env.NODE_ENV === ENV_PROD ? ENV_PROD : ENV_DEV, + debug: process.env.NODE_ENV === ENV_DEV, // debug模式 smtp: { host: 'smtp.example.com', port: 25, - mail: 'service@example.com', - name: '系统邮件', + mail: 'no-reply@example.com', + name: 'no-reply', passwd: '' }, - supportCredentials: false, - credentialsRule: null, - credentialsMaxAge: 0, + cors: { + enabled: false, + credentials: false, + origin: [], // ['abc.com', 'a.foo.com'] + maxAge: 0 + }, jwt: null, // jwt secret regexp: { // 常用正则 email: /^[\w\.\-]+@\w+([\.\-]\w+)*\.\w+$/, uname: /^[A-Za-z\d_]{4,16}$/, - passwd: /^[\S]{6,20}$/, - phone: /^1[34578]\d{9}$/, + passwd: /^\S{6,20}$/, + phone: /^1[3456789]\d{9}$/, idCard: /^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}([0-9]|X|x)$/, - CN: /^[\u4e00-\u9fa5]+$/, + cn: /^[\u4e00-\u9fa5]+$/, qq: /^\d{5,12}$/ } } diff --git a/middleware/credentials.js b/middleware/credentials.js index 9190289..878221e 100644 --- a/middleware/credentials.js +++ b/middleware/credentials.js @@ -7,28 +7,29 @@ import url from 'url' export default function(req, res, next) { - var supportCredentials = this.get('supportCredentials') - var credentialsRule = this.get('credentialsRule') - var credentialsMaxAge = this.get('credentialsMaxAge') + var CORS = this.get('cors') - if (supportCredentials) { + if (CORS.enabled) { var origin = req.header('origin') || req.header('referer') || '' var headers = req.header('access-control-request-headers') - origin = url.parse(origin) + var { hostname, host, protocol } = url.parse(origin) - if (credentialsRule && origin.hostname) { - if (!credentialsRule.test(origin.hostname)) { + if (CORS.origin.length && hostname) { + if (!CORS.origin.includes(hostname)) { return res.end('') } } res.set('Access-Control-Allow-Credentials', 'true') - res.set('Access-Control-Allow-Origin', `${origin.protocol}//${origin.host}`) + res.set('Access-Control-Allow-Origin', `${protocol}//${host}`) + if (headers) { res.set('Access-Control-Allow-Headers', headers) } - if (credentialsMaxAge) { - res.set('Access-Control-Max-Age', credentialsMaxAge) + + if (CORS.maxAge) { + res.set('Access-Control-Max-Age', CORS.maxAge) } + if (req.method === 'OPTIONS') { return res.end('') } diff --git a/middleware/router.js b/middleware/router.js index 5af491f..343d7b8 100644 --- a/middleware/router.js +++ b/middleware/router.js @@ -6,18 +6,14 @@ export default function(req, res, next) { var debug = this.get('debug') + if (this.__MODULES__.__error__) { + var err = this.__MODULES__.__error__ + return res.error(debug ? err.stack || err : err, err.status || 500) + } // 1. 先判断控制器是否存在 if (!this.__MODULES__[req.app]) { - if (this.__MODULES__.__error__) { - res.error( - debug ? this.__MODULES__.__error__.stack : this.__MODULES__.__error__, - 500 - ) - } else { - res.error(`Controller [${req.app}] not found`, 404) - } - return + return res.error(`Controller [${req.app}] not found`, 404) } // 2. 默认二级路由为index @@ -28,29 +24,35 @@ export default function(req, res, next) { // 3. 实例化控制器 this.__MODULES__[req.app] .then(({ default: Mod }) => { - var app = new Mod({ ctx: this, req, res }) - var err = '' + var app, + err = '' + if (Mod) { + app = new Mod({ ctx: this, req, res }) - // action模式, 则路由自动调用对应的action方法 - // __main__模式, 则路由全部走__main__方法 - if (this.get('routeMode') === 'action') { - var route = req.path.shift() - var act = route + 'Action' + // action模式, 则路由自动调用对应的action方法 + // __main__模式, 则路由全部走__main__方法 + if (this.get('routeMode') === 'action') { + var route = req.path.shift() + var act = route + 'Action' - if (app[act]) { - return app[act].apply(app, req.path) + if (app[act]) { + return app[act].apply(app, req.path) + } else { + err = new Error(`Route [${route}] not found`) + } } else { - err = new Error(`Route [${route}] not found`) + if (app.__main__) { + return app.__main__.apply(app, req.path) + } else { + err = new Error('__main__() not found') + } } + err.status = 404 } else { - if (app.__main__) { - return app.__main__.apply(app, req.path) - } else { - err = new Error('__main__() not found') - } + err = new Error(`Controller [${req.app}] load error`) + err.status = 500 } - err.status = 404 return Promise.reject(err) }) .catch(err => {