home.js 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. 'use strict';
  2. const Controller = require('egg').Controller;
  3. const jsonwebtoken = require('jsonwebtoken');
  4. class HomeController extends Controller {
  5. async index() {
  6. const { modules } = this.app.config;
  7. // 路径参数
  8. const { agent, service, module, method, item } = this.ctx.params;
  9. // 请求地址
  10. const address = modules[service];
  11. // 请求方法
  12. const requestMethod = this.ctx.request.method;
  13. // 请求路径
  14. const path = this.ctx.path;
  15. let msg = null;
  16. let details = null;
  17. let result = null;
  18. // jwt 验证
  19. const auth = await this.auth({ service, path });
  20. // 验证失败
  21. if (auth.errcode !== 0) {
  22. this.ctx.status = 401;
  23. this.ctx.body = { errcode: 401, errmsg: '身份验证失败', details: auth.details };
  24. return false;
  25. }
  26. // 发送的数据
  27. let data = requestMethod === 'GET' ? this.ctx.query : this.ctx.request.body;
  28. if (requestMethod === 'DELETE') data = this.ctx.params.item;
  29. // 发送请求
  30. const res = await this.ctx.curl(`${address}${path}`, {
  31. method: requestMethod,
  32. data,
  33. nestedQuerystring: true,
  34. });
  35. // 默认返回值
  36. msg = res.data;
  37. // 日志详情默认值
  38. details = data;
  39. result = '成功';
  40. // 错误异常处理(返回值)
  41. // 缺少字段检测返回asser
  42. if (res.status === 500 && res.data.name === 'AssertionError') {
  43. msg = { errcode: -1002, errmsg: res.data.message, data: '' };
  44. details = res.data.message;
  45. result = '失败';
  46. }
  47. // 异常抛出检测
  48. if (res.status === 500 && (res.data.name === 'ValidationError' || res.data.name === 'CastError')) {
  49. msg = { errcode: -1002, errmsg: '系统错误', details: res.data.message };
  50. details = res.data.message;
  51. result = '失败';
  52. }
  53. await this.setLog({ agent, service, module, method, item, details: JSON.stringify(details), result, auth });
  54. // 默认返回状态 = 当前请求返回状态
  55. this.ctx.response.type = res.headers['content-type'];
  56. this.ctx.status = res.status;
  57. this.ctx.body = msg;
  58. }
  59. // 日志记录
  60. async setLog({ agent, service, module, method, item, details, result, auth }) {
  61. // 配置
  62. const { modules, apipath } = this.app.config;
  63. // 请求路径
  64. const path = this.ctx.path;
  65. // 根据service类型 获取配置文件
  66. const logmodules = apipath[service];
  67. // 没有配置文件默认放过
  68. if (logmodules) {
  69. // const items = logmodules.find(e => e.url.includes(path));
  70. const items = await this.rewrite_path(logmodules, path);
  71. if (items && items.log) {
  72. // 此处开始记录日志
  73. let userName = null;
  74. let name = null;
  75. if (auth.decode) {
  76. userName = auth.decode.userName;
  77. name = auth.decode.name;
  78. }
  79. try {
  80. await this.ctx.curl(`${modules.log}/api/log/log/create`, {
  81. method: 'POST',
  82. dataType: 'json',
  83. data: { agent, service, module, method, item, details, result, userName, name },
  84. });
  85. } catch (error) {
  86. this.ctx.logger.error(`日志添加失败: ${error}`);
  87. }
  88. }
  89. }
  90. }
  91. // 验证函数
  92. async auth({ service, path }) {
  93. const { jwt, apipath } = this.app.config;
  94. // 根据service类型 获取配置文件
  95. const modules = apipath[service];
  96. // 没有配置文件默认放过
  97. if (!modules) return { errcode: 0, details: '' };
  98. // 获取与当前路径匹配的项
  99. // const item = modules.filter(e => e.url.includes(path));
  100. const item = await this.rewrite_path(modules, path);
  101. // 没有匹配数据 默认放过
  102. if (item) return { errcode: 0, details: '' };
  103. // 不验证jwt放过
  104. if (!item.jwt) return { errcode: 0, details: '' };
  105. // 获取token
  106. const token = this.ctx.header.authorization.split('Bearer ')[1];
  107. try {
  108. // 解密jwt
  109. const decode = jsonwebtoken.verify(token, jwt.secret);
  110. // 如果有验证签发者
  111. if (item && item.issuer) {
  112. // 比对签发者
  113. if (!item.issuer.includes(decode.iss)) return { errcode: -4001, details: 'issuer fail verification' };
  114. }
  115. return { errcode: 0, details: '', decode };
  116. } catch (error) {
  117. return { errcode: -4001, details: error.message };
  118. }
  119. }
  120. // 重写路径
  121. async rewrite_path(modules, path) {
  122. return modules.find(e => {
  123. const { url } = e;
  124. let data = null;
  125. const urlList = url.split('/');
  126. const pathIist = path.split('/');
  127. const urlItem = urlList.findIndex(j => j.includes(':'));
  128. if (urlItem > 0) data = pathIist[urlItem];
  129. if (data !== null) urlList[urlItem] = data;
  130. const pathItem = urlList.join('/');
  131. if (pathItem === path) return e;
  132. return false;
  133. });
  134. }
  135. }
  136. module.exports = HomeController;