UNPKG

6.65 kBJavaScriptView Raw
1/*!
2 * MOCK数据服务器
3 * https://github.com/hai2007/mock-servicer
4 *
5 * author hai2007 < https://hai2007.gitee.io/sweethome >
6 *
7 * Copyright (c) 2021-2022 hai2007 走一步,再走一步。
8 * Released under the MIT license
9 */
10
11const http = require('http');
12const { log, fullPath } = require('@hai2007/nodejs');
13const fs = require('fs');
14const path = require('path');
15const url = require('url');
16const mineTypes = require('./mime.types.js');
17const responseFileList = require('./tool/responseFileList.js');
18const urlToString = require('./tool/urlToString');
19
20const jsonfile = JSON.parse(fs.readFileSync(path.join(__dirname, './package.json')));
21
22module.exports = function (config) {
23
24 const port = 'port' in config ? config.port : 8080; // 端口号
25 const basePath = fullPath(config.contentBase || "./", process.cwd());// 根路径
26 const mockBasePath = fullPath(config.mockBase || "./", process.cwd());// 根路径
27
28 http.createServer(function (request, response) {
29
30 let contentType = 'application/json';
31 let responseCode = '200';
32 let responseData = "{}";
33
34 let urlObject = url.parse(request.url);
35
36 // 获取data
37 require('./tool/getData')(request, data => {
38
39 let options = {
40
41 // 请求方法
42 method: request.method,
43
44 // url
45 url: urlObject.pathname.replace(/^\//, '').replace(/\/$/, ''),
46
47 // 请求参数
48 query: require('./tool/toQuery.js')(urlObject.query),
49
50 // 数据
51 value: data
52
53 };
54
55 try {
56 if ('intercept' in config && !config.intercept(options)) {
57 responseCode = "501";
58 responseData = "The current request is not supported.";
59 contentType = 'text/plain';
60 } else {
61
62 // 用于区分这次请求的目的
63 let preUrl = options.url.split('/')[0];
64
65 // 新增或更新
66 // POST localhost:8080/update?url=XXX&method=XXX
67 if (preUrl == 'update') {
68
69 let datapath = fullPath("./mock-" + urlToString(options.query.url, options.query.method) + ".js", mockBasePath);
70
71 // 写入内容
72 fs.writeFileSync(datapath, `module.exports=function(Mock){return ${options.value};};`, {
73 encoding: 'utf8'
74 });
75
76 }
77
78 // 删除
79 // localhost:8080/delete?url=XXX&method=XXX
80 else if (preUrl == 'delete') {
81
82 let datapath = fullPath("./mock-" + urlToString(options.query.url, options.query.method) + ".js", mockBasePath);
83
84 // 删除内容
85 if (fs.existsSync(datapath)) {
86 fs.unlinkSync(datapath);
87 }
88
89 }
90
91 // 查询
92 // localhost:8080/query?url=XXX&method=XXX
93 else if (preUrl == 'query') {
94
95 let datapath = fullPath("./mock-" + urlToString(options.query.url, options.query.method) + ".js", mockBasePath);
96
97 if (fs.existsSync(datapath)) {
98 responseData = JSON.stringify(require(datapath)(require('mockjs')));
99
100 // 删除缓存
101 delete require.cache[require.resolve(datapath)];
102 } else {
103 responseCode = "404";
104 }
105
106 }
107
108 // Mock查询
109 // localhost:8080/mock?XXX
110 else if (preUrl == 'mock') {
111
112 let datapath = fullPath("./" + urlObject.query + ".js", mockBasePath);
113
114 if (fs.existsSync(datapath)) {
115 responseData = JSON.stringify(require(datapath)(require('mockjs')));
116
117 // 删除缓存
118 delete require.cache[require.resolve(datapath)];
119 } else {
120 responseCode = "404";
121 }
122
123 }
124
125 // 原始查询
126 // localhost:8080/oralquery?url=XXX&method=XXX
127 else if (preUrl == 'oralquery') {
128
129 let datapath = fullPath("./mock-" + urlToString(options.query.url, options.query.method) + ".js", mockBasePath);
130
131 if (fs.existsSync(datapath)) {
132 responseData = (fs.readFileSync(datapath, 'utf-8') + "").replace(/^module\.exports=function\(Mock\)\{return /, '').replace(/;\};$/, '');
133 contentType = 'text/plain';
134 } else {
135 responseCode = "404";
136 }
137
138 }
139
140 // 自定义处理
141 // localhost:8080/handler
142 else if (preUrl == 'handler') {
143
144 let resultData = config.handler(options);
145
146 if ('code' in resultData) responseCode = resultData.code;
147 responseData = resultData.data;
148 if ('type' in resultData) contentType = resultData.type;
149
150 }
151
152 // 默认就作为普通的数据服务器
153 else {
154
155 // 请求的文件路径
156 let filePath = fullPath(options.url == "" ? "index.html" : options.url, basePath);
157
158 // 文件后缀名称
159 let dotName = /\./.test(filePath) ? filePath.match(/\.([^.]+)$/)[1] : "";
160
161 // 文件类型
162 if (dotName != "") contentType = mineTypes[dotName];
163
164 // 如果需要读取的文件存在
165 if (fs.existsSync(filePath) && !fs.lstatSync(filePath).isDirectory()) {
166 responseData = fs.readFileSync(filePath);
167 }
168
169 // 如果不存在,就返回404并列举出当前目录内容
170 // 这样的目的是为了方便二次开发
171 else {
172 responseCode = "404";
173 responseData = ('template404' in config ? config.template404 : require('./tool/template404'))(responseFileList(filePath));
174 contentType = "text/html";
175 }
176
177 }
178
179 }
180 }
181
182 // 可能出错
183 catch (e) {
184 responseCode = "500";
185 responseData = "" + e;
186 contentType = 'text/plain';
187 }
188
189 response.writeHead(responseCode, {
190
191 // 设置跨域
192 "Access-Control-Allow-Origin": "*",// 允许的域
193 "Access-Control-Allow-Headers": "*",// 允许的header类型
194 "Access-Control-Allow-Methods": "*",// 允许的请求方法
195
196 // 标记服务器名称
197 "X-Powered-By": jsonfile.name + " " + jsonfile.version,
198
199 // 响应内容类型
200 "Content-Type": contentType + ";charset=utf-8"
201
202 });
203
204 response.write(responseData);
205
206 response.end();
207
208 });
209
210 })
211
212 // 启动监听
213 .listen(port);
214
215 log(jsonfile.name + ' running on port:' + port);
216
217};
\No newline at end of file