wok-server 0.2.2 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. package/dist/config/index.js +17 -3
  2. package/dist/log/file.js +4 -11
  3. package/dist/mvc/config.js +23 -16
  4. package/dist/mvc/handler/json.js +27 -0
  5. package/dist/mvc/index.js +6 -295
  6. package/dist/mvc/render/file.js +3 -85
  7. package/dist/mvc/server.js +263 -0
  8. package/dist/mvc/static/header.js +67 -0
  9. package/dist/mvc/static/index.js +6 -0
  10. package/dist/mvc/static/mime-type.js +84 -0
  11. package/dist/mvc/static/server-cache-config.js +66 -0
  12. package/dist/mvc/static/server-cache.js +133 -0
  13. package/dist/mvc/static/static-handler.js +355 -0
  14. package/dist/mysql/manager/ops/update.js +15 -1
  15. package/dist/validation/index.js +12 -1
  16. package/dist/validation/validator/array.js +7 -11
  17. package/dist/validation/validator/min.js +2 -2
  18. package/documentation/zh-cn/config.md +31 -0
  19. package/documentation/zh-cn/mvc.md +48 -0
  20. package/documentation/zh-cn/mysql.md +72 -0
  21. package/documentation/zh-cn/validate.md +21 -15
  22. package/package.json +1 -1
  23. package/types/config/index.d.ts +10 -0
  24. package/types/mvc/config.d.ts +13 -1
  25. package/types/mvc/handler/json.d.ts +14 -0
  26. package/types/mvc/index.d.ts +3 -36
  27. package/types/mvc/server.d.ts +85 -0
  28. package/types/mvc/static/header.d.ts +27 -0
  29. package/types/mvc/static/index.d.ts +3 -0
  30. package/types/mvc/static/mime-type.d.ts +2 -0
  31. package/types/mvc/static/server-cache-config.d.ts +30 -0
  32. package/types/mvc/static/server-cache.d.ts +76 -0
  33. package/types/mvc/static/static-handler.d.ts +72 -0
  34. package/types/mysql/manager/ops/update.d.ts +7 -1
  35. package/types/validation/validator/array.d.ts +2 -2
  36. package/types/validation/validator/min.d.ts +2 -2
  37. package/types/validation/validator/plain-obj.d.ts +1 -1
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.registerConfig = exports.getConfig = void 0;
3
+ exports.generateConfig = exports.registerConfig = exports.getConfig = void 0;
4
4
  const tslib_1 = require("tslib");
5
5
  const dotenv_1 = require("dotenv");
6
6
  const validation_1 = require("../validation");
@@ -31,6 +31,21 @@ function registerConfig(defaultConfig, envPrefix, validation) {
31
31
  if (configEnvMap.has(envPrefix)) {
32
32
  throw new exception_1.ConfigException(`The prefix "${envPrefix}" has already been registered`);
33
33
  }
34
+ const config = generateConfig(defaultConfig, envPrefix, validation);
35
+ configEnvMap.set(envPrefix, config);
36
+ return config;
37
+ }
38
+ exports.registerConfig = registerConfig;
39
+ /**
40
+ * 根据环境变量来生成配置对象,与 registerConfig 的参数是一致的,和 registerConfig 不同的是
41
+ * generateConfig 可以多次重复使用,方便在运行时更改环境变量后再生成配置,而调用 registerConfig
42
+ * 一旦注册后不能再被更改。之所以这样设计是为了方便程序的测试,模拟不同的环境来运行程序,和其它的
43
+ * 一些特殊需求。
44
+ * @param defaultConfig
45
+ * @param envPrefix
46
+ * @param validation
47
+ */
48
+ function generateConfig(defaultConfig, envPrefix, validation) {
34
49
  // 环境变量匹配
35
50
  for (const propName in defaultConfig) {
36
51
  const defaultVal = defaultConfig[propName];
@@ -53,10 +68,9 @@ function registerConfig(defaultConfig, envPrefix, validation) {
53
68
  throw new exception_1.ConfigException(`Error in verifying configuration information, configuration prefix:${envPrefix}`);
54
69
  }
55
70
  }
56
- configEnvMap.set(envPrefix, defaultConfig);
57
71
  return defaultConfig;
58
72
  }
59
- exports.registerConfig = registerConfig;
73
+ exports.generateConfig = generateConfig;
60
74
  function buildEnvName(envPrefix, propName) {
61
75
  let part2 = propName.replace(/[A-Z]+/g, subStr => `_${subStr}`);
62
76
  if (part2.startsWith('_')) {
package/dist/log/file.js CHANGED
@@ -14,14 +14,7 @@ let QUEUE = [];
14
14
  */
15
15
  function fileStore(log) {
16
16
  QUEUE.push(log);
17
- setTimeout(() => {
18
- try {
19
- write();
20
- }
21
- catch (e) {
22
- console.error('Writing log file failed', e);
23
- }
24
- }, 0);
17
+ setTimeout(() => write().catch(e => console.error('Writing log file failed', e)), 0);
25
18
  }
26
19
  exports.fileStore = fileStore;
27
20
  function buildFilePath() {
@@ -35,18 +28,18 @@ function buildFilePath() {
35
28
  fileName += '.log';
36
29
  return (0, path_1.resolve)(config_1.config.fileDir, fileName);
37
30
  }
38
- function write() {
31
+ async function write() {
39
32
  if (!QUEUE.length) {
40
33
  return;
41
34
  }
42
35
  const path = buildFilePath();
43
36
  const dir = (0, path_1.dirname)(path);
44
37
  if (!(0, fs_1.existsSync)(dir)) {
45
- (0, fs_1.mkdirSync)(dir);
38
+ await (0, promises_1.mkdir)(dir, { recursive: true });
46
39
  }
47
40
  const lines = QUEUE.join(os_1.EOL);
48
- (0, fs_1.appendFileSync)(path, lines);
49
41
  QUEUE = [];
42
+ await (0, promises_1.appendFile)(path, lines);
50
43
  }
51
44
  if (config_1.config.file) {
52
45
  /**
@@ -1,20 +1,27 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.config = void 0;
3
+ exports.getConfig = void 0;
4
4
  const config_1 = require("../config");
5
5
  const validation_1 = require("../validation");
6
- exports.config = (0, config_1.registerConfig)({
7
- port: 8080,
8
- timeout: 30000,
9
- accessLog: false,
10
- corsAllowHeaders: '*',
11
- corsAllowMethods: '*',
12
- corsAllowOrigin: '*'
13
- }, 'SERVER', {
14
- port: [(0, validation_1.notNull)(), (0, validation_1.min)(80), (0, validation_1.max)(65535)],
15
- timeout: [(0, validation_1.notNull)(), (0, validation_1.min)(1000), (0, validation_1.max)(60000)],
16
- accessLog: [(0, validation_1.notNull)()],
17
- corsAllowOrigin: [(0, validation_1.notBlank)()],
18
- corsAllowHeaders: [(0, validation_1.notBlank)()],
19
- corsAllowMethods: [(0, validation_1.notBlank)()]
20
- });
6
+ function getConfig() {
7
+ return (0, config_1.generateConfig)({
8
+ port: 8080,
9
+ timeout: 30000,
10
+ accessLog: false,
11
+ corsAllowHeaders: '*',
12
+ corsAllowMethods: '*',
13
+ corsAllowOrigin: '*',
14
+ tlsEnable: false,
15
+ tlsKey: '',
16
+ tlsCert: ''
17
+ }, 'SERVER', {
18
+ port: [(0, validation_1.notNull)(), (0, validation_1.min)(80), (0, validation_1.max)(65535)],
19
+ timeout: [(0, validation_1.notNull)(), (0, validation_1.min)(1000), (0, validation_1.max)(60000)],
20
+ accessLog: [(0, validation_1.notNull)()],
21
+ corsAllowOrigin: [(0, validation_1.notBlank)()],
22
+ corsAllowHeaders: [(0, validation_1.notBlank)()],
23
+ corsAllowMethods: [(0, validation_1.notBlank)()],
24
+ tlsEnable: [(0, validation_1.notNull)()]
25
+ });
26
+ }
27
+ exports.getConfig = getConfig;
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.createJsonHandler = void 0;
4
+ const cache_1 = require("../../cache");
4
5
  const i18n_1 = require("../../i18n");
5
6
  const validation_1 = require("../../validation");
6
7
  /**
@@ -27,6 +28,26 @@ function createJsonHandler(opts) {
27
28
  (0, validation_1.validate)(body, opts.validation);
28
29
  }
29
30
  }
31
+ // 缓存处理
32
+ if (opts.cache) {
33
+ const cacheInfo = await opts.cache(body, exchange);
34
+ const buffer = (0, cache_1.getCache)().get(cacheInfo.key);
35
+ if (buffer && buffer instanceof Buffer) {
36
+ renderJsonBuffer(exchange, buffer);
37
+ }
38
+ else {
39
+ const res = await opts.handle(body, { request: exchange.request });
40
+ if (!res) {
41
+ // 无结果不缓存
42
+ exchange.respond({ statusCode: 200 });
43
+ return;
44
+ }
45
+ const buffer = Buffer.from(JSON.stringify(res), 'utf-8');
46
+ (0, cache_1.getCache)().put(cacheInfo.key, buffer, cacheInfo.expiresInSeconds);
47
+ renderJsonBuffer(exchange, buffer);
48
+ }
49
+ return;
50
+ }
30
51
  const res = await opts.handle(body, { request: exchange.request });
31
52
  if (!res) {
32
53
  exchange.respond({ statusCode: 200 });
@@ -36,3 +57,9 @@ function createJsonHandler(opts) {
36
57
  };
37
58
  }
38
59
  exports.createJsonHandler = createJsonHandler;
60
+ function renderJsonBuffer(exchange, buffer) {
61
+ const { response } = exchange;
62
+ response.setHeader('content-type', 'application/json; charset=UTF-8');
63
+ response.statusCode = 200;
64
+ response.end(buffer);
65
+ }
package/dist/mvc/index.js CHANGED
@@ -2,193 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.stopWebServer = exports.startWebServer = void 0;
4
4
  const tslib_1 = require("tslib");
5
- const fs_1 = require("fs");
6
- const promises_1 = require("fs/promises");
7
- const http_1 = require("http");
8
- const https_1 = require("https");
9
- const os_1 = require("os");
10
- const path_1 = require("path");
11
- const log_1 = require("../log");
12
- const access_log_1 = require("./access-log");
13
- const config_1 = require("./config");
14
- const exchange_1 = require("./exchange");
15
- const render_1 = require("./render");
16
- /**
17
- * 处理请求,完成拦截器和路由的流程.
18
- *
19
- * @param interceptors 拦截器
20
- * @param routers 路由
21
- * @param req
22
- * @param res
23
- * @param staticSettings
24
- */
25
- async function handleRequest(interceptors, routers, req, res, staticSettings) {
26
- req.socket.remoteAddress;
27
- const { method } = req;
28
- // cros 支持
29
- res.setHeader('Access-Control-Allow-Origin', config_1.config.corsAllowOrigin);
30
- res.setHeader('Access-Control-Allow-Headers', config_1.config.corsAllowHeaders);
31
- res.setHeader('Access-Control-Allow-Methods', config_1.config.corsAllowMethods);
32
- if (method === 'OPTIONS') {
33
- res.statusCode = 200;
34
- res.end();
35
- return;
36
- }
37
- const exchange = new exchange_1.ServerExchange(req, res);
38
- // 顺序执行拦截器
39
- await handleInterceptor(interceptors, 0, exchange, req, res, routers, staticSettings);
40
- }
41
- /**
42
- * 处理拦截器.
43
- * @param interceptors 拦截器
44
- * @param idx 当前要执行的拦截器下标
45
- * @param exchange 传输对象
46
- * @param req
47
- * @param res
48
- * @param routers 路由
49
- * @param staticSettings
50
- */
51
- async function handleInterceptor(interceptors, idx, exchange, req, res, routers, staticSettings) {
52
- const interceptor = interceptors[idx];
53
- // 到最后一个了,那么执行路由处理
54
- if (!interceptor) {
55
- await handleRouter(exchange, routers, staticSettings);
56
- return;
57
- }
58
- await interceptor(exchange, () => handleInterceptor(interceptors, idx + 1, exchange, req, res, routers, staticSettings));
59
- }
60
- /**
61
- * 处理路由.
62
- * @param exchange
63
- * @param routers
64
- * @param staticSettings
65
- * @returns
66
- */
67
- async function handleRouter(exchange, routers, staticSettings) {
68
- const url = exchange.request.url;
69
- if (url === undefined) {
70
- return;
71
- }
72
- // 判定路由
73
- const idx = url.indexOf('?');
74
- let path = idx === -1 ? url : url.substring(0, idx);
75
- const router = routers[path];
76
- if (!router) {
77
- // 路由找不不到,尝试静态文件
78
- if ((exchange.request.method || '').toLowerCase() === 'get' && staticSettings.length) {
79
- await handleStatic(exchange, routers, path, staticSettings);
80
- }
81
- else {
82
- respond404(exchange, routers, path);
83
- }
84
- return;
85
- }
86
- // 执行路由
87
- await router(exchange);
88
- // 在路由顺利处理的情况下,如果 res 没有 end ,就表示响应没有完成
89
- // 也就是说路由没有做响应处理,或处理没有完成就结束了,给予错误提示
90
- if (!exchange.response.writableEnded) {
91
- throw new Error(`RouterHandler unresponsive, url: ${url}`);
92
- }
93
- }
94
- /**
95
- * 处理静态文件
96
- * @param exchange
97
- * @param routers
98
- * @param path
99
- * @param staticDir
100
- * @returns
101
- */
102
- async function handleStatic(exchange, routers, path, staticSettings) {
103
- // 匹配
104
- let matchedSetting;
105
- for (const setting of staticSettings) {
106
- if (setting.path === '/') {
107
- matchedSetting = setting;
108
- break;
109
- }
110
- if (path.startsWith(setting.path)) {
111
- matchedSetting = setting;
112
- break;
113
- }
114
- }
115
- if (!matchedSetting) {
116
- respond404(exchange, routers, path);
117
- return;
118
- }
119
- let finalPath = matchedSetting.path === '/' ? path : path.substring(matchedSetting.path.length);
120
- if (finalPath.startsWith('/')) {
121
- finalPath = finalPath.substring(1);
122
- }
123
- const fullPath = (0, path_1.resolve)(matchedSetting.dir, finalPath);
124
- if (!(0, fs_1.existsSync)(fullPath)) {
125
- respond404(exchange, routers, path);
126
- return;
127
- }
128
- const statRes = await (0, promises_1.stat)(fullPath);
129
- // 目录,寻找 index.html
130
- if (statRes.isDirectory()) {
131
- const indexPath = (0, path_1.resolve)(fullPath, 'index.html');
132
- if (!(0, fs_1.existsSync)(indexPath)) {
133
- respond404(exchange, routers, path);
134
- return;
135
- }
136
- const indexStat = await (0, promises_1.stat)(indexPath);
137
- if (!indexStat.isFile()) {
138
- respond404(exchange, routers, path);
139
- return;
140
- }
141
- // Cache-Control
142
- if (matchedSetting.cacheAge >= 0) {
143
- exchange.response.setHeader('Cache-Control', matchedSetting.cacheAge === 0 ? 'no-store' : `max-age=${matchedSetting.cacheAge}`);
144
- }
145
- await exchange.respondFile(indexPath, false);
146
- return;
147
- }
148
- // 文件直接渲染
149
- if (statRes.isFile()) {
150
- // Cache-Control
151
- if (matchedSetting.cacheAge >= 0) {
152
- exchange.response.setHeader('Cache-Control', matchedSetting.cacheAge === 0 ? 'no-store' : `max-age=${matchedSetting.cacheAge}`);
153
- }
154
- await exchange.respondFile(fullPath, false);
155
- return;
156
- }
157
- // 其它类型,404
158
- respond404(exchange, routers, path);
159
- }
160
- /**
161
- * 404响应
162
- *
163
- * @param exchange
164
- * @param routers
165
- * @param path
166
- */
167
- async function respond404(exchange, routers, path) {
168
- const handler = routers['*'];
169
- if (handler) {
170
- await handler(exchange);
171
- }
172
- else {
173
- exchange.respondErrMsg(`${path} not found`, 404);
174
- }
175
- }
176
- /**
177
- * 获取 ipv4 地址列表
178
- * @returns
179
- */
180
- function getIpv4List() {
181
- const ifs = (0, os_1.networkInterfaces)();
182
- const res = [];
183
- for (const name in ifs) {
184
- const list = ifs[name];
185
- if (!list) {
186
- continue;
187
- }
188
- res.push(...list.filter(info => info.family === 'IPv4').map(info => info.address));
189
- }
190
- return res;
191
- }
5
+ const server_1 = require("./server");
192
6
  /**
193
7
  * 服务实例.
194
8
  */
@@ -198,103 +12,11 @@ let SERVER;
198
12
  * @param opts
199
13
  */
200
14
  async function startWebServer(opts) {
201
- (0, https_1.createServer)({
202
- cert: '', key: ''
203
- }, () => {
204
- });
205
15
  if (SERVER) {
206
16
  throw new Error('The server has already been started!');
207
17
  }
208
- // 检查静态文件配置,做一些预处理的操作,在处理静态资源的请求时不必再做这些处理
209
- const staticSettings = [];
210
- if (opts.static) {
211
- // 重复记录表 ,作用是为了路径去重判定,可以提示哪些路径是重复的
212
- const duplicateMap = new Map();
213
- for (const entry of Object.entries(opts.static)) {
214
- const [path, setting] = entry;
215
- const dir = (0, path_1.isAbsolute)(setting.dir) ? setting.dir : (0, path_1.resolve)(process.cwd(), setting.dir);
216
- if (!(0, fs_1.existsSync)(dir)) {
217
- throw new Error(`Static file configuration error,path ${dir} does not exist,config dir:${setting.dir}`);
218
- }
219
- const statRes = await (0, promises_1.stat)(dir);
220
- if (!statRes.isDirectory()) {
221
- throw new Error(`Static file configuration error,path ${dir} is not a directory,config dir:${setting.dir}`);
222
- }
223
- let finalPath = path.startsWith('/') ? path : '/' + path;
224
- // 保持以 / 结尾,为了匹配方便
225
- if (!finalPath.endsWith('/')) {
226
- finalPath += '/';
227
- }
228
- if (duplicateMap.has(finalPath)) {
229
- throw new Error(`Static path duplicated: ${duplicateMap.get(finalPath)} and ${path}`);
230
- }
231
- duplicateMap.set(finalPath, path);
232
- staticSettings.push({ path: finalPath, dir, cacheAge: setting.cacheAge || 0 });
233
- }
234
- // 优先级排序
235
- staticSettings.sort((o1, o2) => {
236
- let priority1 = o1.path === '/' ? -1 : o1.path.split('/').length;
237
- let priority2 = o2.path === '/' ? -1 : o2.path.split('/').length;
238
- // 如果 o1 优先级高,就应该排前面,返回小于0的值,反之亦然\
239
- // 前面的优先级值是值越大优先级越高,反过来减
240
- return priority2 - priority1;
241
- });
242
- }
243
- // 如果启用请求日志,增加拦截器
244
- let interceptors = [];
245
- if (config_1.config.accessLog) {
246
- interceptors.push(access_log_1.accessLogInterceptor);
247
- }
248
- if (opts.interceptors) {
249
- interceptors.push(...opts.interceptors);
250
- }
251
- SERVER = (0, http_1.createServer)((req, res) => {
252
- res.setHeader('Server', 'Wok Server');
253
- res.on('error', error => {
254
- // 如果响应流发生错误,只能把信息记录下来
255
- (0, log_1.getLogger)().error(`Response Error:${req.url}`, error);
256
- });
257
- handleRequest(interceptors, opts.routers, req, res, staticSettings).catch(error => {
258
- (0, log_1.getLogger)().error(`Handle request failed:${req.url}`, error);
259
- if (!res.writableEnded) {
260
- // 响应 500
261
- (0, render_1.renderError)(res, error.message ? error.message : 'Internal Server Error', 500);
262
- }
263
- });
264
- });
265
- SERVER.setTimeout(config_1.config.timeout);
266
- SERVER.on('timeout', (socket) => {
267
- socket.end('HTTP/1.1 408 Timeout\ncontent-type: application/json; charset=utf-8\n\n{"message":"Request timeout"}');
268
- });
269
- if (opts.preHandler) {
270
- await opts.preHandler(SERVER);
271
- }
272
- const server = SERVER;
273
- await new Promise((resolve, reject) => {
274
- server.on('error', e => {
275
- if (e.code === 'EADDRINUSE') {
276
- reject(`Port ${config_1.config.port} is already in use.`);
277
- }
278
- else {
279
- reject(e);
280
- }
281
- });
282
- server.listen(config_1.config.port, resolve);
283
- });
284
- console.log('App running at: ');
285
- getIpv4List().forEach(ip => {
286
- if (config_1.config.port === 80) {
287
- console.log(`http://${ip}`);
288
- }
289
- else {
290
- console.log(`http://${ip}:${config_1.config.port}`);
291
- }
292
- });
293
- process.on('beforeExit', () => {
294
- if (server.listening) {
295
- server.close();
296
- }
297
- });
18
+ SERVER = new server_1.WokServer(opts);
19
+ await SERVER.start();
298
20
  }
299
21
  exports.startWebServer = startWebServer;
300
22
  /**
@@ -305,24 +27,13 @@ async function stopWebServer() {
305
27
  if (!SERVER) {
306
28
  return;
307
29
  }
308
- if (SERVER.listening) {
309
- const server = SERVER;
310
- await new Promise((res, rej) => {
311
- server.close(err => {
312
- if (err) {
313
- rej(err);
314
- }
315
- else {
316
- res();
317
- }
318
- });
319
- });
320
- }
30
+ SERVER.stop();
321
31
  SERVER = undefined;
322
32
  }
323
33
  exports.stopWebServer = stopWebServer;
34
+ process.on('beforeExit', stopWebServer);
324
35
  tslib_1.__exportStar(require("./exchange"), exports);
325
36
  tslib_1.__exportStar(require("./handler"), exports);
37
+ tslib_1.__exportStar(require("./interceptor"), exports);
326
38
  tslib_1.__exportStar(require("./render"), exports);
327
39
  tslib_1.__exportStar(require("./router"), exports);
328
- tslib_1.__exportStar(require("./interceptor"), exports);
@@ -3,92 +3,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.renderFile = void 0;
4
4
  const fs_1 = require("fs");
5
5
  const promises_1 = require("fs/promises");
6
- const json_1 = require("./json");
7
6
  const path_1 = require("path");
8
7
  const zlib_1 = require("zlib");
9
- /**
10
- * 常用的 content-type 对照表
11
- */
12
- const frequentlyUsedContentTypeTable = {
13
- aac: 'audio/aac',
14
- abw: 'application/x-abiword',
15
- arc: 'application/x-freearc',
16
- avi: 'video/x-msvideo',
17
- azw: 'application/vnd.amazon.ebook',
18
- bin: 'application/octet-stream',
19
- bmp: 'image/bmp',
20
- bz: 'application/x-bzip',
21
- bz2: 'application/x-bzip2',
22
- csh: 'application/x-csh',
23
- css: 'text/css',
24
- csv: 'text/csv',
25
- doc: 'application/msword',
26
- docx: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
27
- eot: 'application/vnd.ms-fontobject',
28
- epub: 'application/epub+zip',
29
- gif: 'image/gif',
30
- htm: 'text/html',
31
- html: 'text/html',
32
- ico: 'image/vnd.microsoft.icon',
33
- ics: 'text/calendar',
34
- jar: 'application/java-archive',
35
- jpeg: 'image/jpeg',
36
- jpg: 'image/jpeg',
37
- js: 'text/javascript',
38
- json: 'application/json',
39
- jsonld: 'application/ld+json',
40
- mid: 'audio/midi',
41
- midi: 'audio/midi',
42
- mjs: 'text/javascript',
43
- mp3: 'audio/mpeg',
44
- mpeg: 'video/mpeg',
45
- mpkg: 'application/vnd.apple.installer+xml',
46
- odp: 'application/vnd.oasis.opendocument.presentation',
47
- ods: 'application/vnd.oasis.opendocument.spreadsheet',
48
- odt: 'application/vnd.oasis.opendocument.text',
49
- oga: 'audio/ogg',
50
- ogv: 'video/ogg',
51
- ogx: 'application/ogg',
52
- otf: 'font/otf',
53
- png: 'image/png',
54
- pdf: 'application/pdf',
55
- ppt: 'application/vnd.ms-powerpoint',
56
- pptx: 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
57
- rar: 'application/x-rar-compressed',
58
- rtf: 'application/rtf',
59
- sh: 'application/x-sh',
60
- svg: 'image/svg+xml',
61
- swf: 'application/x-shockwave-flash',
62
- tar: 'application/x-tar',
63
- tif: 'image/tiff',
64
- tiff: 'image/tiff',
65
- ttf: 'font/ttf',
66
- txt: 'text/plain',
67
- vsd: 'application/vnd.visio',
68
- wav: 'audio/wav',
69
- weba: 'audio/webm',
70
- webm: 'video/webm',
71
- webp: 'image/webp',
72
- woff: 'font/woff',
73
- woff2: 'font/woff2',
74
- xhtml: 'application/xhtml+xml',
75
- xls: 'application/vnd.ms-excel',
76
- xlsx: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
77
- xml: 'application/xml',
78
- xul: 'application/vnd.mozilla.xul+xml',
79
- zip: 'application/zip',
80
- '3gp': 'video/3gpp',
81
- '3g2': 'video/3gpp2',
82
- '7z': 'application/x-7z-compressed'
83
- };
84
- function decideContentType(fileName) {
85
- const idx = fileName.lastIndexOf('.');
86
- if (idx === -1) {
87
- return undefined;
88
- }
89
- const suffix = fileName.substring(idx + 1);
90
- return frequentlyUsedContentTypeTable[suffix];
91
- }
8
+ const static_1 = require("../static");
9
+ const json_1 = require("./json");
92
10
  /**
93
11
  * 响应一个文件.
94
12
  * @param request 请求信息
@@ -108,7 +26,7 @@ async function renderFile(request, response, filePath, download = false) {
108
26
  isDownload = true;
109
27
  }
110
28
  else {
111
- contentType = decideContentType(fileName);
29
+ contentType = (0, static_1.decideContentType)(fileName);
112
30
  if (!contentType) {
113
31
  isDownload = true;
114
32
  }