UNPKG

whistle.mock-plugins

Version:

Whistle 插件,用于快速创建 API 模拟数据

513 lines (451 loc) 17.9 kB
const fs = require('fs-extra'); const path = require('path'); module.exports = function(req, res) { const dataDir = this.dataDir; const interfacesFile = path.join(dataDir, 'interfaces.json'); const featuresFile = path.join(dataDir, 'features.json'); try { // 确保配置文件存在并包含有效结构 if (!fs.existsSync(interfacesFile)) { fs.writeJsonSync(interfacesFile, { interfaces: [] }, { spaces: 2 }); } else { // 验证文件结构 try { const fileData = fs.readJsonSync(interfacesFile); if (!fileData || !fileData.interfaces) { // 如果文件存在但结构无效,重新初始化 fs.writeJsonSync(interfacesFile, { interfaces: [] }, { spaces: 2 }); console.log('修复了损坏的interfaces文件结构'); } } catch (e) { // JSON解析错误时重新初始化文件 fs.writeJsonSync(interfacesFile, { interfaces: [] }, { spaces: 2 }); console.log('修复了无法解析的interfaces文件'); } } // 处理GET请求 - 获取接口列表 if (req.method === 'GET') { const { featureId } = req.query; if (!featureId) { return res.status(400).json({ code: 400, message: '功能ID不能为空', data: null }); } // 检查功能是否存在 let featureExists = false; if (fs.existsSync(featuresFile)) { try { const featuresData = fs.readJsonSync(featuresFile); if (featuresData && featuresData.features) { const feature = featuresData.features.find(item => item.id === featureId); featureExists = !!feature; } if (!featureExists) { return res.status(404).json({ code: 404, message: '功能模块不存在', data: null }); } } catch (err) { console.error('读取功能文件错误:', err); // 出错时继续处理 } } // 读取接口数据 let interfacesData; try { interfacesData = fs.readJsonSync(interfacesFile); if (!interfacesData || !interfacesData.interfaces) { interfacesData = { interfaces: [] }; } } catch (err) { console.error('读取接口列表错误:', err); interfacesData = { interfaces: [] }; } const filteredInterfaces = interfacesData.interfaces.filter(item => item.featureId === featureId); console.log('GET获取接口列表:', { featureId, totalCount: filteredInterfaces.length, interfacesWithResponses: filteredInterfaces.map(item => ({ name: item.name, hasResponses: !!item.responses, responsesCount: item.responses ? item.responses.length : 0, activeResponseId: item.activeResponseId })) }); return res.json({ code: 0, message: '成功', data: filteredInterfaces }); } // 处理POST请求 - 添加或更新接口 if (req.method === 'POST') { const interfaceData = req.body; // 参数验证 if (!interfaceData.featureId) { return res.status(400).json({ code: 400, message: '功能ID不能为空', data: null }); } if (!interfaceData.name) { return res.status(400).json({ code: 400, message: '接口名称不能为空', data: null }); } if (!interfaceData.urlPattern) { return res.status(400).json({ code: 400, message: 'URL匹配规则不能为空', data: null }); } // 检查是否响应内容过大,超过100MB时给予特殊处理 if (interfaceData.responseContent && Buffer.byteLength(interfaceData.responseContent, 'utf8') > 100 * 1024 * 1024) { return res.status(413).json({ code: 413, message: '响应内容过大,超过100MB限制', data: null }); } // 检查功能是否存在 let featureExists = false; if (fs.existsSync(featuresFile)) { try { const featuresData = fs.readJsonSync(featuresFile); if (featuresData && featuresData.features) { const feature = featuresData.features.find(item => item.id === interfaceData.featureId); featureExists = !!feature; } if (!featureExists) { return res.status(404).json({ code: 404, message: '功能模块不存在', data: null }); } } catch (err) { console.error('读取功能文件错误:', err); // 忽略错误继续处理 } } // 读取接口数据 let interfacesData; try { interfacesData = fs.readJsonSync(interfacesFile); if (!interfacesData || !interfacesData.interfaces) { interfacesData = { interfaces: [] }; } } catch (err) { console.error('读取接口列表错误:', err); interfacesData = { interfaces: [] }; } // 如果有ID则更新,否则创建新接口 if (interfaceData.id) { // 更新现有接口 const index = interfacesData.interfaces.findIndex(item => item.id === interfaceData.id); if (index === -1) { return res.status(404).json({ code: 404, message: '接口不存在', data: null }); } // 更新接口 interfacesData.interfaces[index] = { ...interfacesData.interfaces[index], name: interfaceData.name, group: interfaceData.group !== undefined ? interfaceData.group : interfacesData.interfaces[index].group || '', // 添加分组字段 urlPattern: interfaceData.urlPattern, proxyType: interfaceData.proxyType, responseContent: interfaceData.responseContent, responses: interfaceData.responses || interfacesData.interfaces[index].responses || [], activeResponseId: interfaceData.activeResponseId !== undefined ? interfaceData.activeResponseId : interfacesData.interfaces[index].activeResponseId, targetUrl: interfaceData.targetUrl, customHeaders: interfaceData.customHeaders || {}, paramMatchers: interfaceData.paramMatchers || [], filePath: interfaceData.filePath, httpStatus: interfaceData.httpStatus || 200, responseDelay: interfaceData.responseDelay || 0, httpMethod: interfaceData.httpMethod || 'ALL', active: interfaceData.active !== false }; console.log('更新接口,包含多响应数据:', { name: interfacesData.interfaces[index].name, responsesCount: interfacesData.interfaces[index].responses.length, activeResponseId: interfacesData.interfaces[index].activeResponseId }); fs.writeJsonSync(interfacesFile, interfacesData, { spaces: 2 }); return res.json({ code: 0, message: '接口更新成功', data: interfacesData.interfaces[index] }); } else { // 创建新接口 const newInterface = { id: Date.now().toString(), featureId: interfaceData.featureId, name: interfaceData.name, group: interfaceData.group || '', // 添加分组字段 urlPattern: interfaceData.urlPattern, proxyType: interfaceData.proxyType || 'response', responseContent: interfaceData.responseContent || '', responses: interfaceData.responses || [], activeResponseId: interfaceData.activeResponseId || null, targetUrl: interfaceData.targetUrl || '', customHeaders: interfaceData.customHeaders || {}, paramMatchers: interfaceData.paramMatchers || [], filePath: interfaceData.filePath || '', httpStatus: interfaceData.httpStatus || 200, responseDelay: interfaceData.responseDelay || 0, httpMethod: interfaceData.httpMethod || 'ALL', active: interfaceData.active !== false, contentType: interfaceData.contentType || 'text/plain' }; console.log('创建新接口,包含多响应数据:', { name: newInterface.name, group: newInterface.group, // 添加分组日志 responsesCount: newInterface.responses.length, activeResponseId: newInterface.activeResponseId }); // 确保interfaces数组存在 if (!Array.isArray(interfacesData.interfaces)) { interfacesData.interfaces = []; } interfacesData.interfaces.push(newInterface); fs.writeJsonSync(interfacesFile, interfacesData, { spaces: 2 }); return res.json({ code: 0, message: '接口创建成功', data: newInterface }); } } // 处理DELETE请求 - 删除接口 if (req.method === 'DELETE') { const { id } = req.query; if (!id) { return res.status(400).json({ code: 400, message: '接口ID不能为空', data: null }); } let interfacesData; try { interfacesData = fs.readJsonSync(interfacesFile); if (!interfacesData || !interfacesData.interfaces) { interfacesData = { interfaces: [] }; } } catch (err) { console.error('读取接口列表错误:', err); interfacesData = { interfaces: [] }; } const index = interfacesData.interfaces.findIndex(item => item.id === id); if (index === -1) { return res.status(404).json({ code: 404, message: '接口不存在', data: null }); } // 删除接口 const deletedInterface = interfacesData.interfaces.splice(index, 1)[0]; fs.writeJsonSync(interfacesFile, interfacesData, { spaces: 2 }); return res.json({ code: 0, message: '接口删除成功', data: deletedInterface }); } // 处理 PUT 请求 - 更新接口 if (req.method === 'PUT') { const { id } = req.query; const interfaceData = req.body; if (!id) { return res.status(400).json({ code: 400, message: '接口ID不能为空', data: null }); } // 读取接口数据 let interfacesData; try { interfacesData = fs.readJsonSync(interfacesFile); if (!interfacesData || !interfacesData.interfaces) { interfacesData = { interfaces: [] }; } } catch (err) { console.error('读取接口列表错误:', err); return res.status(500).json({ code: 500, message: '读取接口数据失败', data: null }); } // 查找并更新接口 const index = interfacesData.interfaces.findIndex(item => item.id === id); if (index === -1) { return res.status(404).json({ code: 404, message: '接口不存在', data: null }); } // 更新接口数据 const updatedInterface = { ...interfacesData.interfaces[index], name: interfaceData.name || interfacesData.interfaces[index].name, group: interfaceData.group !== undefined ? interfaceData.group : interfacesData.interfaces[index].group || '', // 添加分组字段 urlPattern: interfaceData.urlPattern || interfacesData.interfaces[index].urlPattern, proxyType: interfaceData.proxyType || interfacesData.interfaces[index].proxyType, responseContent: interfaceData.responseContent !== undefined ? interfaceData.responseContent : interfacesData.interfaces[index].responseContent, responses: interfaceData.responses !== undefined ? interfaceData.responses : (interfacesData.interfaces[index].responses || []), activeResponseId: interfaceData.activeResponseId !== undefined ? interfaceData.activeResponseId : interfacesData.interfaces[index].activeResponseId, targetUrl: interfaceData.targetUrl !== undefined ? interfaceData.targetUrl : interfacesData.interfaces[index].targetUrl, customHeaders: interfaceData.customHeaders !== undefined ? interfaceData.customHeaders : interfacesData.interfaces[index].customHeaders || {}, paramMatchers: interfaceData.paramMatchers !== undefined ? interfaceData.paramMatchers : interfacesData.interfaces[index].paramMatchers || [], filePath: interfaceData.filePath !== undefined ? interfaceData.filePath : interfacesData.interfaces[index].filePath, httpStatus: interfaceData.httpStatus || interfacesData.interfaces[index].httpStatus, responseDelay: interfaceData.responseDelay !== undefined ? interfaceData.responseDelay : interfacesData.interfaces[index].responseDelay, httpMethod: interfaceData.httpMethod || interfacesData.interfaces[index].httpMethod, active: interfaceData.active !== undefined ? interfaceData.active : interfacesData.interfaces[index].active, contentType: interfaceData.contentType || interfacesData.interfaces[index].contentType, updatedAt: new Date().toISOString() }; console.log('PUT更新接口,包含多响应数据:', { name: updatedInterface.name, group: updatedInterface.group, // 添加分组日志 responsesCount: updatedInterface.responses.length, activeResponseId: updatedInterface.activeResponseId }); interfacesData.interfaces[index] = updatedInterface; fs.writeJsonSync(interfacesFile, interfacesData, { spaces: 2 }); return res.json({ code: 0, message: '接口更新成功', data: updatedInterface }); } // 处理 PATCH 请求 - 部分更新接口(如启用/禁用状态) if (req.method === 'PATCH') { // 从URL路径参数或查询参数中获取ID const id = req.params?.id || req.query?.id; const { active } = req.query; const patchData = req.body; // 读取接口数据 let interfacesData; try { interfacesData = fs.readJsonSync(interfacesFile); if (!interfacesData || !interfacesData.interfaces) { interfacesData = { interfaces: [] }; } } catch (err) { console.error('读取接口列表错误:', err); return res.status(500).json({ code: 500, message: '读取接口数据失败', data: null }); } // 批量更新接口状态 if (active !== undefined) { const { featureId, group } = patchData; if (!featureId) { return res.status(400).json({ code: 400, message: '功能ID不能为空', data: null }); } // 根据分组筛选要更新的接口 let updatedCount = 0; interfacesData.interfaces = interfacesData.interfaces.map(item => { // 只更新指定功能模块下的接口 if (item.featureId !== featureId) { return item; } // 如果指定了分组,只更新该分组下的接口 if (group && item.group !== group) { return item; } // 更新接口状态 const isActive = active === 'true'; if (item.active !== isActive) { updatedCount++; return { ...item, active: isActive, updatedAt: new Date().toISOString() }; } return item; }); // 保存更新后的接口列表 fs.writeJsonSync(interfacesFile, interfacesData, { spaces: 2 }); console.log(`批量${active === 'true' ? '启用' : '禁用'}接口:`, { featureId, group, updatedCount }); return res.json({ code: 0, message: `成功${active === 'true' ? '启用' : '禁用'} ${updatedCount} 个接口`, data: { updatedCount } }); } // 单个接口更新 if (!id) { return res.status(400).json({ code: 400, message: '接口ID不能为空', data: null }); } // 查找接口 const index = interfacesData.interfaces.findIndex(item => item.id === id); if (index === -1) { return res.status(404).json({ code: 404, message: '接口不存在', data: null }); } // 部分更新接口数据 const updatedInterface = { ...interfacesData.interfaces[index], ...patchData, updatedAt: new Date().toISOString() }; interfacesData.interfaces[index] = updatedInterface; fs.writeJsonSync(interfacesFile, interfacesData, { spaces: 2 }); return res.json({ code: 0, message: '接口更新成功', data: updatedInterface }); } // 其他请求方法 return res.status(405).json({ code: 405, message: '不支持的请求方法', data: null }); } catch (err) { console.error('处理接口请求出错:', err); return res.status(500).json({ code: 500, message: '服务器内部错误: ' + err.message, data: null }); } };