mock平台

controller.js 14KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288
  1. const baseController = require('controllers/base.js');
  2. const interfaceModel = require('models/interface.js');
  3. const projectModel = require('models/project.js');
  4. const interfaceCatModel = require('models/interfaceCat.js');
  5. const yapi = require('yapi.js');
  6. class exportSwaggerController extends baseController {
  7. constructor(ctx) {
  8. super(ctx);
  9. this.catModel = yapi.getInst(interfaceCatModel);
  10. this.interModel = yapi.getInst(interfaceModel);
  11. this.projectModel = yapi.getInst(projectModel);
  12. }
  13. /*
  14. handleListClass,handleExistId is same as the exportController(yapi-plugin-export-data).
  15. No DRY,but i have no idea to optimize it.
  16. */
  17. async handleListClass(pid, status) {
  18. let result = await this.catModel.list(pid),
  19. newResult = [];
  20. for (let i = 0, item, list; i < result.length; i++) {
  21. item = result[i].toObject();
  22. list = await this.interModel.listByInterStatus(item._id, status);
  23. list = list.sort((a, b) => {
  24. return a.index - b.index;
  25. });
  26. if (list.length > 0) {
  27. item.list = list;
  28. newResult.push(item);
  29. }
  30. }
  31. return newResult;
  32. }
  33. handleExistId(data) {
  34. function delArrId(arr, fn) {
  35. if (!Array.isArray(arr)) return;
  36. arr.forEach(item => {
  37. delete item._id;
  38. delete item.__v;
  39. delete item.uid;
  40. delete item.edit_uid;
  41. delete item.catid;
  42. delete item.project_id;
  43. if (typeof fn === 'function') fn(item);
  44. });
  45. }
  46. delArrId(data, function (item) {
  47. delArrId(item.list, function (api) {
  48. delArrId(api.req_body_form);
  49. delArrId(api.req_params);
  50. delArrId(api.req_query);
  51. delArrId(api.req_headers);
  52. if (api.query_path && typeof api.query_path === 'object') {
  53. delArrId(api.query_path.params);
  54. }
  55. });
  56. });
  57. return data;
  58. }
  59. async exportData(ctx) {
  60. let pid = ctx.request.query.pid;
  61. let type = ctx.request.query.type;
  62. let status = ctx.request.query.status;
  63. if (!pid) {
  64. ctx.body = yapi.commons.resReturn(null, 200, 'pid 不为空');
  65. }
  66. let curProject;
  67. let tp = '';
  68. try {
  69. curProject = await this.projectModel.get(pid);
  70. ctx.set('Content-Type', 'application/octet-stream');
  71. const list = await this.handleListClass(pid, status);
  72. switch (type) {
  73. case 'OpenAPIV2':
  74. { //in this time, only implemented OpenAPI V2.0
  75. let data = this.handleExistId(list);
  76. let model = await convertToSwaggerV2Model(data);
  77. tp = JSON.stringify(model, null, 2);
  78. ctx.set('Content-Disposition', `attachment; filename=swaggerApi.json`);
  79. return (ctx.body = tp);
  80. }
  81. default:
  82. {
  83. ctx.body = yapi.commons.resReturn(null, 400, 'type 无效参数')
  84. }
  85. }
  86. } catch (error) {
  87. yapi.commons.log(error, 'error');
  88. ctx.body = yapi.commons.resReturn(null, 502, '下载出错');
  89. }
  90. //Convert to SwaggerV2.0 (OpenAPI 2.0)
  91. async function convertToSwaggerV2Model(list) {
  92. const swaggerObj = {
  93. swagger: '2.0',
  94. info: {
  95. title: curProject.name,
  96. version: 'last', // last version
  97. description: curProject.desc
  98. },
  99. //host: "", // No find any info of host in this point :-)
  100. basePath: curProject.basepath ? curProject.basepath : '/', //default base path is '/'(root)
  101. tags: (() => {
  102. let tagArray = [];
  103. list.forEach(t => {
  104. tagArray.push({
  105. name: t.name,
  106. description: t.desc
  107. /*externalDocs:{
  108. descroption:"",
  109. url:""
  110. } */
  111. });
  112. });
  113. return tagArray;
  114. })(),
  115. schemes: [
  116. "http" //Only http
  117. ],
  118. paths: (() => {
  119. let apisObj = {};
  120. for (let aptTag of list) { //list of category
  121. for (let api of aptTag.list) //list of api
  122. {
  123. if (apisObj[api.path] == null) {
  124. apisObj[api.path] = {};
  125. }
  126. apisObj[api.path][api.method.toLowerCase()] = (() => {
  127. let apiItem = {};
  128. apiItem['tags'] = [aptTag.name];
  129. apiItem['summary'] = api.title;
  130. apiItem['description'] = api.markdown;
  131. switch (api.req_body_type) {
  132. case 'form':
  133. case 'file':
  134. apiItem['consumes'] = ['multipart/form-data']; //form data required
  135. break;
  136. case 'json':
  137. apiItem['consumes'] = ['application/json'];
  138. break;
  139. case 'raw':
  140. apiItem['consumes'] = ['text/plain'];
  141. break;
  142. default:
  143. break;
  144. }
  145. apiItem['parameters'] = (() => {
  146. let paramArray = [];
  147. for (let p of api.req_headers) //Headers parameters
  148. {
  149. //swagger has consumes proprety, so skip proprety "Content-Type"
  150. if (p.name === 'Content-Type') {
  151. continue;
  152. }
  153. paramArray.push({
  154. name: p.name,
  155. in: 'header',
  156. description: `${p.name} (Only:${p.value})`,
  157. required: p.required === 1,
  158. type: 'string', //always be type string
  159. default: p.value
  160. });
  161. }
  162. for (let p of api.req_params) //Path parameters
  163. {
  164. paramArray.push({
  165. name: p.name,
  166. in: 'path',
  167. description: p.desc,
  168. required: true, //swagger path parameters required proprety must be always true,
  169. type: 'string' //always be type string
  170. });
  171. }
  172. for (let p of api.req_query) //Query parameters
  173. {
  174. paramArray.push({
  175. name: p.name,
  176. in: 'query',
  177. required: p.required === 1,
  178. description: p.desc,
  179. type: 'string' //always be type string
  180. });
  181. }
  182. switch (api.req_body_type) //Body parameters
  183. {
  184. case 'form':
  185. {
  186. for (let p of api.req_body_form) {
  187. paramArray.push({
  188. name: p.name,
  189. in: 'formData',
  190. required: p.required === 1,
  191. description: p.desc,
  192. type: p.type === 'text' ? 'string' : 'file' //in this time .formData type have only text or file
  193. });
  194. }
  195. break;
  196. }
  197. case 'json':
  198. {
  199. if (api.req_body_other) {
  200. let jsonParam = JSON.parse(api.req_body_other);
  201. if (jsonParam) {
  202. paramArray.push({
  203. name: 'root',
  204. in: 'body',
  205. description: jsonParam.description,
  206. schema: jsonParam //as same as swagger's format
  207. });
  208. }
  209. }
  210. break;
  211. }
  212. case 'file':
  213. {
  214. paramArray.push({
  215. name: 'upfile',
  216. in: 'formData', //use formData
  217. description: api.req_body_other,
  218. type: 'file'
  219. });
  220. break;
  221. }
  222. case 'raw':
  223. {
  224. paramArray.push({
  225. name: 'raw',
  226. in: 'body',
  227. description: 'raw paramter',
  228. schema: {
  229. type: 'string',
  230. format: 'binary',
  231. default: api.req_body_other
  232. }
  233. });
  234. break;
  235. }
  236. default:
  237. break;
  238. }
  239. return paramArray;
  240. })();
  241. apiItem['responses'] = {
  242. '200': {
  243. description: 'successful operation',
  244. schema: (() => {
  245. let schemaObj = {};
  246. if (api.res_body_type === 'raw') {
  247. schemaObj['type'] = 'string';
  248. schemaObj['format'] = 'binary';
  249. schemaObj['default'] = api.res_body;
  250. } else if (api.res_body_type === 'json') {
  251. if (api.res_body) {
  252. let resBody = JSON.parse(api.res_body);
  253. if (resBody !== null) {
  254. //schemaObj['type']=resBody.type;
  255. schemaObj = resBody; //as the parameters,
  256. }
  257. }
  258. }
  259. return schemaObj;
  260. })()
  261. }
  262. };
  263. return apiItem;
  264. })();
  265. }
  266. }
  267. return apisObj;
  268. })()
  269. };
  270. return swaggerObj;
  271. }
  272. }
  273. }
  274. module.exports = exportSwaggerController;