mock平台

server.js 5.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. const controller = require('./controller');
  2. const advModel = require('./advMockModel.js');
  3. const caseModel = require('./caseModel.js');
  4. const yapi = require('yapi.js');
  5. const mongoose = require('mongoose');
  6. const _ = require('underscore');
  7. const path = require('path');
  8. const lib = require(path.resolve(yapi.WEBROOT, 'common/lib.js'));
  9. const Mock = require('mockjs');
  10. const mockExtra = require(path.resolve(yapi.WEBROOT, 'common/mock-extra.js'));
  11. function arrToObj(arr) {
  12. let obj = { 'Set-Cookie': [] };
  13. arr.forEach(item => {
  14. if (item.name === 'Set-Cookie') {
  15. obj['Set-Cookie'].push(item.value);
  16. } else obj[item.name] = item.value;
  17. });
  18. return obj;
  19. }
  20. module.exports = function() {
  21. yapi.connect.then(function() {
  22. let Col = mongoose.connection.db.collection('adv_mock');
  23. Col.createIndex({
  24. interface_id: 1
  25. });
  26. Col.createIndex({
  27. project_id: 1
  28. });
  29. let caseCol = mongoose.connection.db.collection('adv_mock_case');
  30. caseCol.createIndex({
  31. interface_id: 1
  32. });
  33. caseCol.createIndex({
  34. project_id: 1
  35. });
  36. });
  37. async function checkCase(ctx, interfaceId) {
  38. let reqParams = Object.assign({}, ctx.query, ctx.request.body);
  39. let caseInst = yapi.getInst(caseModel);
  40. // let ip = ctx.ip.match(/\d+.\d+.\d+.\d+/)[0];
  41. // request.ip
  42. let ip = yapi.commons.getIp(ctx);
  43. // 数据库信息查询
  44. // 过滤 开启IP
  45. let listWithIp = await caseInst.model
  46. .find({
  47. interface_id: interfaceId,
  48. ip_enable: true,
  49. ip: ip
  50. })
  51. .select('_id params case_enable');
  52. let matchList = [];
  53. listWithIp.forEach(item => {
  54. let params = item.params;
  55. if (item.case_enable && lib.isDeepMatch(reqParams, params)) {
  56. matchList.push(item);
  57. }
  58. });
  59. // 其他数据
  60. if (matchList.length === 0) {
  61. let list = await caseInst.model
  62. .find({
  63. interface_id: interfaceId,
  64. ip_enable: false
  65. })
  66. .select('_id params case_enable');
  67. list.forEach(item => {
  68. let params = item.params;
  69. if (item.case_enable && lib.isDeepMatch(reqParams, params)) {
  70. matchList.push(item);
  71. }
  72. });
  73. }
  74. if (matchList.length > 0) {
  75. let maxItem = _.max(matchList, item => (item.params && Object.keys(item.params).length) || 0);
  76. return maxItem;
  77. }
  78. return null;
  79. }
  80. async function handleByCase(caseData) {
  81. let caseInst = yapi.getInst(caseModel);
  82. let result = await caseInst.get({
  83. _id: caseData._id
  84. });
  85. return result;
  86. }
  87. this.bindHook('add_router', function(addRouter) {
  88. addRouter({
  89. controller: controller,
  90. method: 'get',
  91. path: 'advmock/get',
  92. action: 'getMock'
  93. });
  94. addRouter({
  95. controller: controller,
  96. method: 'post',
  97. path: 'advmock/save',
  98. action: 'upMock'
  99. });
  100. addRouter({
  101. /**
  102. * 保存期望
  103. */
  104. controller: controller,
  105. method: 'post',
  106. path: 'advmock/case/save',
  107. action: 'saveCase'
  108. });
  109. addRouter({
  110. controller: controller,
  111. method: 'get',
  112. path: 'advmock/case/get',
  113. action: 'getCase'
  114. });
  115. addRouter({
  116. /**
  117. * 获取期望列表
  118. */
  119. controller: controller,
  120. method: 'get',
  121. path: 'advmock/case/list',
  122. action: 'list'
  123. });
  124. addRouter({
  125. /**
  126. * 删除期望列表
  127. */
  128. controller: controller,
  129. method: 'post',
  130. path: 'advmock/case/del',
  131. action: 'delCase'
  132. });
  133. addRouter({
  134. /**
  135. * 隐藏期望列表
  136. */
  137. controller: controller,
  138. method: 'post',
  139. path: 'advmock/case/hide',
  140. action: 'hideCase'
  141. });
  142. });
  143. this.bindHook('interface_del', async function(id) {
  144. let inst = yapi.getInst(advModel);
  145. await inst.delByInterfaceId(id);
  146. });
  147. this.bindHook('project_del', async function(id) {
  148. let inst = yapi.getInst(advModel);
  149. await inst.delByProjectId(id);
  150. });
  151. /**
  152. * let context = {
  153. projectData: project,
  154. interfaceData: interfaceData,
  155. ctx: ctx,
  156. mockJson: res
  157. }
  158. */
  159. this.bindHook('mock_after', async function(context) {
  160. let interfaceId = context.interfaceData._id;
  161. let caseData = await checkCase(context.ctx, interfaceId);
  162. // 只有开启高级mock才可用
  163. if (caseData && caseData.case_enable) {
  164. // 匹配到高级mock
  165. let data = await handleByCase(caseData);
  166. context.mockJson = yapi.commons.json_parse(data.res_body);
  167. try {
  168. context.mockJson = Mock.mock(
  169. mockExtra(context.mockJson, {
  170. query: context.ctx.query,
  171. body: context.ctx.request.body,
  172. params: Object.assign({}, context.ctx.query, context.ctx.request.body)
  173. })
  174. );
  175. } catch (err) {
  176. yapi.commons.log(err, 'error');
  177. }
  178. context.resHeader = arrToObj(data.headers);
  179. context.httpCode = data.code;
  180. context.delay = data.delay;
  181. return true;
  182. }
  183. let inst = yapi.getInst(advModel);
  184. let data = await inst.get(interfaceId);
  185. if (!data || !data.enable || !data.mock_script) {
  186. return context;
  187. }
  188. // mock 脚本
  189. let script = data.mock_script;
  190. yapi.commons.handleMockScript(script, context);
  191. });
  192. };