// 引入Node.js的path模块,用于处理文件路径相关操作 var path = require('path'); // 原本要引入的roles控制器模块,此处被注释掉了,可能后续会按需启用 // var roles_controller = require("../controllers/roles"); // 再次引入path模块,前面的引入语句重复了,但在Node.js中不会有实质影响,可考虑优化掉重复引入的情况 var path = require("path"); // 创建一个全局对象service_caches,用于缓存服务相关的模块或数据,初始为空对象 global.service_caches = {}; // 创建一个全局变量service_auth_fn,用于存储全局验证函数,初始值为null global.service_auth_fn = null; /** * Invocation函数用于构造一个回调对象格式,主要用于在调用服务的具体方法时进行权限验证等相关操作。 * * @param {[type]} serviceName 服务名称,用于标识具体是哪个服务。 * @param {[type]} actionName 动作名称(方法名),对应服务模块里具体的函数名称。 * @param {[type]} serviceModule 服务模块,即通过require加载进来的包含具体业务逻辑函数的模块对象。 * @param {[type]} origFunc 原始方法,也就是服务模块里未经包装的原始业务逻辑函数。 */ function Invocation(serviceName, actionName, serviceModule, origFunc) { // 返回一个新的函数,这个函数会接收一些参数(此处未在形参中体现,在调用时会传入),并返回另一个函数作为真正的回调函数 return function () { var origArguments = arguments; return function (req, res, next) { // 判断全局验证函数是否存在,如果存在则进行权限验证流程 if (global.service_auth_fn) { global.service_auth_fn(req, res, next, serviceName, actionName, function (pass) { // 如果权限验证通过(pass为true),则执行原始的业务逻辑函数 if (pass) { origFunc.apply(serviceModule, origArguments); } else { // 如果权限验证失败,向客户端返回相应的错误信息,状态码为401表示未授权 res.sendResult(null, 401, "权限验证失败"); } }); } else { // 如果全局验证函数不存在,直接返回权限验证失败的错误信息给客户端 res.sendResult(null, 401, "权限验证失败"); } } } } // 定义一个函数用于获取服务对象,它是模块对外暴露的接口之一 module.exports.getService = function (serviceName) { // 先检查全局缓存中是否已经存在指定名称的服务对象,如果存在则直接返回缓存中的服务对象 if (global.service_caches[serviceName]) { return global.service_caches[serviceName]; } // 构建服务模块的文件路径,通过拼接当前工作目录、"services"文件夹以及服务名称来确定具体路径 var servicePath = path.join(process.cwd(), "services", serviceName); // 通过require加载对应的服务模块,如果模块不存在则返回null并在控制台打印提示信息 var serviceModule = require(servicePath); if (!serviceModule) { console.log("模块没有被发现"); return null; } // 在全局缓存对象中为当前服务名称创建一个空对象,用于后续存储该服务的具体方法相关的回调对象等信息 global.service_caches[serviceName] = {}; // 打印一些提示信息,表明正在拦截指定名称的服务,方便调试和查看流程 console.log("*****************************************"); console.log("拦截服务 => %s", serviceName); console.log("*****************************************"); // 遍历服务模块里的所有属性(通常是方法) for (actionName in serviceModule) { // 检查属性对应的是否是一个函数(即服务模块里有效的业务逻辑函数) if (serviceModule && serviceModule[actionName] && typeof (serviceModule[actionName]) == "function") { var origFunc = serviceModule[actionName]; // 使用Invocation函数构造该方法对应的回调对象,并将其存储到全局缓存对象中对应的服务和方法名下 global.service_caches[serviceName][actionName] = Invocation(serviceName, actionName, serviceModule, origFunc); console.log("action => %s", actionName); } } // 打印一些分割线和空行,用于在控制台输出中更清晰地区分不同服务的处理情况,此处注释掉了打印全局缓存对象的语句 // console.log(global.service_caches); console.log("*****************************************\n"); return global.service_caches[serviceName]; } // 定义一个函数用于设置全局验证函数,它也是模块对外暴露的接口,供外部传入具体的验证函数 module.exports.setAuthFn = function (authFn) { global.service_auth_fn = authFn; }