'use strict'; const Controller = require('egg').Controller; const jsonwebtoken = require('jsonwebtoken'); const FormStream = require('formstream'); class HomeController extends Controller { async index() { const { modules } = this.app.config; // 路径参数 const { agent, service, module, method, item } = this.ctx.params; // 请求地址 const address = modules[service]; // 请求方法 const requestMethod = this.ctx.request.method; // 请求路径 const path = this.ctx.path; let msg = null; let details = null; let result = null; // jwt 验证 const auth = await this.auth({ service, path }); // 验证失败 if (auth.errcode !== 0) { this.ctx.status = 401; this.ctx.body = { errcode: 401, errmsg: '身份验证失败', details: auth.details }; return false; } // 发送的数据 let data = requestMethod === 'GET' ? this.ctx.query : this.ctx.request.body; if (requestMethod === 'DELETE') data = this.ctx.params.item; // 参数定义 let form = {}; const options = { method: requestMethod, data, nestedQuerystring: true, }; // 如果是文件上传 if (method === 'upload') { const stream = await this.ctx.getFileStream(); form = new FormStream(); form.stream(stream.fieldname, stream, stream.filename); options.stream = form; options.headers = form.headers(); } // 发送请求 const res = await this.ctx.curl(`${address}${path}`, options); // 默认返回值 msg = res.data; // 日志详情默认值 details = data; result = '成功'; // 错误异常处理(返回值) // 异常抛出检测 if (res.status === 500) { msg = { errcode: -1002, errmsg: '系统错误', details: '未知错误类型' }; details = {}; result = '失败'; } // 缺少字段检测返回asser if (res.status === 500 && res.data.name === 'AssertionError') { msg = { errcode: -1002, errmsg: res.data.message, data: '' }; details = res.data.message; result = '失败'; } // 异常抛出检测 if (res.status === 500 && (res.data.name === 'ValidationError' || res.data.name === 'CastError')) { msg = { errcode: -1002, errmsg: '系统错误', details: res.data.message }; details = res.data.message; result = '失败'; } await this.setLog({ agent, service, module, method, item, details: JSON.stringify(details), result, auth }); // 默认返回状态 = 当前请求返回状态 this.ctx.response.type = res.headers['content-type']; this.ctx.status = res.status; this.ctx.body = msg; } // 日志记录 async setLog({ agent, service, module, method, item, details, result, auth }) { // 配置 const { modules, apipath } = this.app.config; // 请求路径 const path = this.ctx.path; // 根据service类型 获取配置文件 const logmodules = apipath[service]; // 没有配置文件默认放过 if (logmodules) { // const items = logmodules.find(e => e.url.includes(path)); const items = await this.rewrite_path(logmodules, path); if (items && items.log) { // 此处开始记录日志 let userName = null; let name = null; if (auth.decode) { userName = auth.decode.userName; name = auth.decode.name; } try { await this.ctx.curl(`${modules.log}/api/log/log/create`, { method: 'POST', dataType: 'json', data: { agent, service, module, method, item, details, result, userName, name }, }); } catch (error) { this.ctx.logger.error(`日志添加失败: ${error}`); } } } } // 验证函数 async auth({ service, path }) { const { jwt, apipath } = this.app.config; // 根据service类型 获取配置文件 const modules = apipath[service]; // 没有配置文件默认放过 if (!modules) return { errcode: 0, details: '' }; // 获取与当前路径匹配的项 // const item = modules.filter(e => e.url.includes(path)); const item = await this.rewrite_path(modules, path); // 没有匹配数据 默认放过 不验证jwt放过 if (!item || !item.jwt) return { errcode: 0, details: '' }; // 获取token const token = this.ctx.header.authorization; try { // 解密jwt const decode = jsonwebtoken.verify(token, jwt.secret); // 如果有验证签发者 if (item && item.issuer) { // 比对签发者 if (!item.issuer.includes(decode.iss)) return { errcode: -4001, details: 'issuer fail verification' }; } return { errcode: 0, details: '', decode: decode._doc }; } catch (error) { return { errcode: -4001, details: error.message }; } } // 重写路径 async rewrite_path(modules, path) { return modules.find(e => { const { url } = e; let data = null; const urlList = url.split('/'); const pathIist = path.split('/'); const urlItem = urlList.findIndex(j => j.includes(':')); if (urlItem > 0) data = pathIist[urlItem]; if (data !== null) urlList[urlItem] = data; const pathItem = urlList.join('/'); if (pathItem === path) return e; return false; }); } } module.exports = HomeController;