@maiyunnet/kebab 2.0.0

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 (114) hide show
  1. package/.VSCodeCounter/2025-02-14_14-46-44/details.md +82 -0
  2. package/.VSCodeCounter/2025-02-14_14-46-44/diff-details.md +15 -0
  3. package/.VSCodeCounter/2025-02-14_14-46-44/diff.csv +2 -0
  4. package/.VSCodeCounter/2025-02-14_14-46-44/diff.md +19 -0
  5. package/.VSCodeCounter/2025-02-14_14-46-44/diff.txt +22 -0
  6. package/.VSCodeCounter/2025-02-14_14-46-44/results.csv +69 -0
  7. package/.VSCodeCounter/2025-02-14_14-46-44/results.json +1 -0
  8. package/.VSCodeCounter/2025-02-14_14-46-44/results.md +48 -0
  9. package/.VSCodeCounter/2025-02-14_14-46-44/results.txt +118 -0
  10. package/.vscode/tasks.json +15 -0
  11. package/LICENSE +201 -0
  12. package/README.md +201 -0
  13. package/bin/kebab.js +2 -0
  14. package/eslint.config.js +22 -0
  15. package/index.js +19 -0
  16. package/index.ts +33 -0
  17. package/lib/buffer.js +108 -0
  18. package/lib/buffer.ts +152 -0
  19. package/lib/captcha/zcool-addict-italic.ttf +0 -0
  20. package/lib/captcha.js +71 -0
  21. package/lib/captcha.ts +63 -0
  22. package/lib/consistent.js +171 -0
  23. package/lib/consistent.ts +219 -0
  24. package/lib/core.js +663 -0
  25. package/lib/core.ts +880 -0
  26. package/lib/crypto.js +256 -0
  27. package/lib/crypto.ts +384 -0
  28. package/lib/db.js +521 -0
  29. package/lib/db.ts +719 -0
  30. package/lib/dns.js +321 -0
  31. package/lib/dns.ts +405 -0
  32. package/lib/fs.js +405 -0
  33. package/lib/fs.ts +527 -0
  34. package/lib/jwt.js +223 -0
  35. package/lib/jwt.ts +276 -0
  36. package/lib/kv.js +1004 -0
  37. package/lib/kv.ts +1489 -0
  38. package/lib/lan.js +99 -0
  39. package/lib/lan.ts +87 -0
  40. package/lib/net/cacert.pem +3480 -0
  41. package/lib/net/formdata.js +137 -0
  42. package/lib/net/formdata.ts +166 -0
  43. package/lib/net/request.js +102 -0
  44. package/lib/net/request.ts +150 -0
  45. package/lib/net/response.js +28 -0
  46. package/lib/net/response.ts +59 -0
  47. package/lib/net.js +462 -0
  48. package/lib/net.ts +662 -0
  49. package/lib/s3.js +180 -0
  50. package/lib/s3.ts +235 -0
  51. package/lib/scan.js +276 -0
  52. package/lib/scan.ts +364 -0
  53. package/lib/session.js +177 -0
  54. package/lib/session.ts +230 -0
  55. package/lib/sql.js +818 -0
  56. package/lib/sql.ts +1151 -0
  57. package/lib/ssh/sftp.js +373 -0
  58. package/lib/ssh/sftp.ts +508 -0
  59. package/lib/ssh/shell.js +109 -0
  60. package/lib/ssh/shell.ts +123 -0
  61. package/lib/ssh.js +171 -0
  62. package/lib/ssh.ts +191 -0
  63. package/lib/text/tld.json +1 -0
  64. package/lib/text.js +452 -0
  65. package/lib/text.ts +607 -0
  66. package/lib/time.js +216 -0
  67. package/lib/time.ts +254 -0
  68. package/lib/ws.js +373 -0
  69. package/lib/ws.ts +523 -0
  70. package/lib/zip.js +381 -0
  71. package/lib/zip.ts +447 -0
  72. package/lib/zlib.js +289 -0
  73. package/lib/zlib.ts +350 -0
  74. package/main.js +51 -0
  75. package/main.ts +27 -0
  76. package/package.json +37 -0
  77. package/sys/child.js +585 -0
  78. package/sys/child.ts +678 -0
  79. package/sys/cmd.js +226 -0
  80. package/sys/cmd.ts +225 -0
  81. package/sys/ctr.js +608 -0
  82. package/sys/ctr.ts +904 -0
  83. package/sys/master.js +314 -0
  84. package/sys/master.ts +355 -0
  85. package/sys/mod.js +1273 -0
  86. package/sys/mod.ts +1871 -0
  87. package/sys/route.js +922 -0
  88. package/sys/route.ts +1113 -0
  89. package/types/index.d.ts +283 -0
  90. package/www/example/ctr/main.js +42 -0
  91. package/www/example/ctr/main.ts +9 -0
  92. package/www/example/ctr/middle.js +57 -0
  93. package/www/example/ctr/middle.ts +26 -0
  94. package/www/example/ctr/test.js +2818 -0
  95. package/www/example/ctr/test.ts +3218 -0
  96. package/www/example/data/locale/en.test.json +8 -0
  97. package/www/example/data/locale/index.html +1 -0
  98. package/www/example/data/locale/ja.test.json +8 -0
  99. package/www/example/data/locale/sc.test.json +8 -0
  100. package/www/example/data/locale/tc.test.json +8 -0
  101. package/www/example/data/test.zip +0 -0
  102. package/www/example/kebab.json +24 -0
  103. package/www/example/mod/test.js +49 -0
  104. package/www/example/mod/test.ts +47 -0
  105. package/www/example/mod/testdata.js +11 -0
  106. package/www/example/mod/testdata.ts +30 -0
  107. package/www/example/route.json +6 -0
  108. package/www/example/view/test.ejs +11 -0
  109. package/www/example/ws/mproxy.js +49 -0
  110. package/www/example/ws/mproxy.ts +16 -0
  111. package/www/example/ws/rproxy.js +47 -0
  112. package/www/example/ws/rproxy.ts +14 -0
  113. package/www/example/ws/test.js +68 -0
  114. package/www/example/ws/test.ts +36 -0
package/sys/route.js ADDED
@@ -0,0 +1,922 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.clearKebabConfigs = clearKebabConfigs;
37
+ exports.run = run;
38
+ exports.unlinkUploadFiles = unlinkUploadFiles;
39
+ exports.waitCtr = waitCtr;
40
+ exports.trimPost = trimPost;
41
+ exports.getFormData = getFormData;
42
+ const http = __importStar(require("http"));
43
+ const stream = __importStar(require("stream"));
44
+ const ws = __importStar(require("@litert/websocket"));
45
+ const lFs = __importStar(require("~/lib/fs"));
46
+ const lZlib = __importStar(require("~/lib/zlib"));
47
+ const lCore = __importStar(require("~/lib/core"));
48
+ const lText = __importStar(require("~/lib/text"));
49
+ const lTime = __importStar(require("~/lib/time"));
50
+ const lResponse = __importStar(require("~/lib/net/response"));
51
+ const lWs = __importStar(require("~/lib/ws"));
52
+ const sCtr = __importStar(require("./ctr"));
53
+ const kebab = __importStar(require("~/index"));
54
+ let kebabConfigs = {};
55
+ function clearKebabConfigs() {
56
+ kebabConfigs = {};
57
+ }
58
+ async function run(data) {
59
+ if (/^(stc\/.*|favicon.\w+?\??.*|apple[\w-]+?\.png\??.*|[\w-]+?\.txt\??.*|[\w-]+?\.html\??.*)/.test(data.path)) {
60
+ return false;
61
+ }
62
+ if (data.res) {
63
+ data.res.setHeader('expires', 'Mon, 26 Jul 1994 05:00:00 GMT');
64
+ data.res.setHeader('cache-control', 'no-store');
65
+ }
66
+ if (!kebabConfigs[data.rootPath + 'kebab.json']) {
67
+ const configContent = await lFs.getContent(data.rootPath + 'kebab.json', 'utf8');
68
+ if (!configContent) {
69
+ if (data.res) {
70
+ data.res.setHeader('content-length', 53);
71
+ data.res.writeHead(500);
72
+ data.res.end('<h1>500 File kebab.json can not be read</h1><hr>Kebab');
73
+ }
74
+ else {
75
+ data.socket?.destroy();
76
+ }
77
+ return true;
78
+ }
79
+ kebabConfigs[data.rootPath + 'kebab.json'] = lText.parseJson(configContent);
80
+ const routeContent = await lFs.getContent(data.rootPath + 'route.json', 'utf8');
81
+ if (routeContent) {
82
+ kebabConfigs[data.rootPath + 'kebab.json'].route = lText.parseJson(routeContent);
83
+ }
84
+ for (const name in lCore.globalConfig) {
85
+ if (typeof lCore.globalConfig[name] !== 'object') {
86
+ if (kebabConfigs[data.rootPath + 'kebab.json'][name] === undefined) {
87
+ kebabConfigs[data.rootPath + 'kebab.json'][name] = lCore.globalConfig[name];
88
+ }
89
+ continue;
90
+ }
91
+ for (const name2 in lCore.globalConfig[name]) {
92
+ if (kebabConfigs[data.rootPath + 'kebab.json'][name] === undefined) {
93
+ kebabConfigs[data.rootPath + 'kebab.json'][name] = {};
94
+ }
95
+ if (kebabConfigs[data.rootPath + 'kebab.json'][name][name2] === undefined) {
96
+ kebabConfigs[data.rootPath + 'kebab.json'][name][name2] = lCore.globalConfig[name][name2];
97
+ }
98
+ }
99
+ }
100
+ }
101
+ const config = {};
102
+ const configData = kebabConfigs[data.rootPath + 'kebab.json'];
103
+ for (const name in configData) {
104
+ config[name] = configData[name];
105
+ }
106
+ config.const = {
107
+ 'path': data.path,
108
+ 'qs': data.uri.query ?? '',
109
+ 'startTime': process.hrtime.bigint(),
110
+ 'startMemory': process.memoryUsage().rss,
111
+ 'mobile': data.req.headers['user-agent'] ? data.req.headers['user-agent'].includes('mobile') : false,
112
+ 'wechat': data.req.headers['user-agent'] ? data.req.headers['user-agent'].includes('micromessenger') : false,
113
+ 'https': data.uri.protocol === 'https' ? true : false,
114
+ 'host': data.uri.host ?? '',
115
+ 'hostname': data.uri.hostname ?? '',
116
+ 'hostport': data.uri.port ? parseInt(data.uri.port) : (data.uri.protocol === 'https' ? 443 : 80),
117
+ 'uri': data.uri,
118
+ 'rootPath': data.rootPath,
119
+ 'ctrPath': data.rootPath + 'ctr/',
120
+ 'viewPath': data.rootPath + 'view/',
121
+ 'dataPath': data.rootPath + 'data/',
122
+ 'modPath': data.rootPath + 'mod/',
123
+ 'wsPath': data.rootPath + 'ws/',
124
+ 'urlBase': data.urlBase,
125
+ 'urlStc': data.urlBase + 'stc/',
126
+ 'urlFull': (data.uri.protocol ?? '') + '//' + (data.uri.host ?? '') + data.urlBase,
127
+ 'urlStcFull': ''
128
+ };
129
+ config.const.urlStcFull = config.const.urlFull + 'stc/';
130
+ if (!config.set.staticPath) {
131
+ config.set.staticPath = config.const.urlStc;
132
+ }
133
+ if (!config.set.staticPathFull) {
134
+ config.set.staticPathFull = config.const.urlStcFull;
135
+ }
136
+ let path = data.path;
137
+ if (path === '') {
138
+ path = '@';
139
+ }
140
+ const param = [];
141
+ if (config.lang && data.res) {
142
+ if (path[2] !== '/') {
143
+ let isDirect = false;
144
+ if (!path) {
145
+ if (config.lang.direct.includes('@')) {
146
+ isDirect = true;
147
+ }
148
+ }
149
+ else {
150
+ for (const ditem of config.lang.direct) {
151
+ if (!path.startsWith(ditem)) {
152
+ continue;
153
+ }
154
+ isDirect = true;
155
+ break;
156
+ }
157
+ }
158
+ if (!isDirect) {
159
+ const alang = data.req.headers['accept-language']?.toLowerCase() ?? config.lang.list[0];
160
+ const apath = config.const.path + (config.const.qs ? '?' + config.const.qs : '');
161
+ for (const lang of config.lang.list) {
162
+ let checkLang = lang;
163
+ if (lang === 'sc') {
164
+ checkLang = 'cn';
165
+ }
166
+ else if (lang === 'tc') {
167
+ checkLang = 'zh';
168
+ }
169
+ if (!alang.includes(checkLang)) {
170
+ continue;
171
+ }
172
+ data.res.setHeader('location', config.const.urlBase + lang + '/' + apath);
173
+ data.res.writeHead(302);
174
+ data.res.end('');
175
+ return true;
176
+ }
177
+ data.res.setHeader('location', config.const.urlBase + config.lang.list[0] + '/' + apath);
178
+ data.res.writeHead(302);
179
+ data.res.end('');
180
+ return true;
181
+ }
182
+ }
183
+ else {
184
+ param.push(path.slice(0, 2));
185
+ path = path.slice(3);
186
+ if (!path) {
187
+ path = '@';
188
+ }
189
+ }
190
+ }
191
+ let match = null;
192
+ let pathLeft = '', pathRight = '';
193
+ for (const rule in config.route) {
194
+ const ruleVal = config.route[rule];
195
+ if ((match = (new RegExp('^' + rule + '$')).exec(path))) {
196
+ if (data.res) {
197
+ [pathLeft, pathRight] = getPathLeftRight(ruleVal);
198
+ }
199
+ else {
200
+ pathLeft = getWsCtrName(ruleVal);
201
+ }
202
+ for (let i = 1; i < match.length; ++i) {
203
+ param.push(match[i]);
204
+ }
205
+ break;
206
+ }
207
+ }
208
+ if (!match) {
209
+ if (data.res) {
210
+ [pathLeft, pathRight] = getPathLeftRight(path);
211
+ }
212
+ else {
213
+ pathLeft = getWsCtrName(path);
214
+ }
215
+ }
216
+ if (pathLeft.startsWith('middle')) {
217
+ const text = '[Error] Controller not found, path: ' + path + '.';
218
+ if (data.res) {
219
+ if (config.route['#404']) {
220
+ data.res.setHeader('location', lText.urlResolve(config.const.urlBase, config.route['#404']));
221
+ data.res.writeHead(302);
222
+ data.res.end('');
223
+ return true;
224
+ }
225
+ data.res.setHeader('content-type', 'text/html; charset=utf-8');
226
+ data.res.setHeader('content-length', Buffer.byteLength(text));
227
+ data.res.writeHead(404);
228
+ data.res.end(text);
229
+ }
230
+ else {
231
+ data.socket?.destroy();
232
+ }
233
+ return true;
234
+ }
235
+ const get = data.uri.query ? lText.queryParse(data.uri.query) : {};
236
+ const cookies = {};
237
+ if (data.req.headers['cookie']) {
238
+ const hcookies = data.req.headers['cookie'].split(';');
239
+ for (const cookie of hcookies) {
240
+ const co = cookie.split('=');
241
+ cookies[co[0].trim()] = decodeURIComponent(co[1]);
242
+ }
243
+ }
244
+ const headers = {};
245
+ for (const key in data.req.headers) {
246
+ headers[key.toLowerCase()] = data.req.headers[key];
247
+ }
248
+ headers['authorization'] ??= '';
249
+ let rtn;
250
+ if (data.socket && data.req instanceof http.IncomingMessage) {
251
+ const filePath = config.const.wsPath + pathLeft + '.js';
252
+ if (!await lFs.isFile(filePath)) {
253
+ data.socket?.destroy();
254
+ return true;
255
+ }
256
+ const ctrCtr = (await Promise.resolve(`${filePath}`).then(s => __importStar(require(s)))).default;
257
+ const cctr = new ctrCtr(config, data.req);
258
+ let wsSocket;
259
+ try {
260
+ const options = await cctr.onUpgrade();
261
+ wsSocket = lWs.createServer(data.req, data.socket, options);
262
+ cctr.setPrototype('_socket', wsSocket);
263
+ }
264
+ catch (e) {
265
+ await lCore.log(cctr, lText.stringifyJson(e.stack).slice(1, -1), '-error');
266
+ data.socket.destroy();
267
+ return true;
268
+ }
269
+ cctr.setPrototype('_param', param);
270
+ cctr.setPrototype('_action', pathRight);
271
+ cctr.setPrototype('_headers', headers);
272
+ cctr.setPrototype('_get', get);
273
+ cctr.setPrototype('_cookie', cookies);
274
+ await lCore.log(cctr, '', '-visit');
275
+ try {
276
+ rtn = await cctr.onLoad();
277
+ }
278
+ catch (e) {
279
+ await lCore.log(cctr, lText.stringifyJson(e.stack).slice(1, -1), '-error');
280
+ data.socket.destroy();
281
+ return true;
282
+ }
283
+ if (rtn === undefined || rtn === true) {
284
+ await new Promise(function (resolve) {
285
+ wsSocket.on('message', async function (msg) {
286
+ switch (msg.opcode) {
287
+ case ws.EOpcode.CLOSE: {
288
+ const r = await cctr['onMessage'](msg.data, msg.opcode);
289
+ if (r === false) {
290
+ break;
291
+ }
292
+ wsSocket.end();
293
+ break;
294
+ }
295
+ case ws.EOpcode.PING: {
296
+ const r = await cctr['onMessage'](msg.data, msg.opcode);
297
+ if (r === false) {
298
+ break;
299
+ }
300
+ wsSocket.pong();
301
+ break;
302
+ }
303
+ case ws.EOpcode.BINARY:
304
+ case ws.EOpcode.TEXT: {
305
+ try {
306
+ const r = await cctr['onMessage'](msg.data, msg.opcode);
307
+ if (r === false) {
308
+ break;
309
+ }
310
+ const wrtn = await cctr['onData'](msg.data, msg.opcode);
311
+ if (wrtn === false) {
312
+ wsSocket.end();
313
+ return;
314
+ }
315
+ if (!wrtn) {
316
+ return;
317
+ }
318
+ if (wrtn instanceof Buffer) {
319
+ wsSocket.writeBinary(wrtn);
320
+ return;
321
+ }
322
+ if (typeof wrtn === 'string') {
323
+ if (!wrtn) {
324
+ return;
325
+ }
326
+ wsSocket.writeText(wrtn);
327
+ return;
328
+ }
329
+ if (typeof wrtn === 'object') {
330
+ wsSocket.writeResult(wrtn);
331
+ return;
332
+ }
333
+ }
334
+ catch (e) {
335
+ await lCore.log(cctr, lText.stringifyJson(e.stack).slice(1, -1), '-error');
336
+ }
337
+ break;
338
+ }
339
+ default: {
340
+ }
341
+ }
342
+ }).on('drain', async () => {
343
+ try {
344
+ await cctr['onDrain']();
345
+ }
346
+ catch (e) {
347
+ await lCore.log(cctr, lText.stringifyJson(e.stack).slice(1, -1), '-error');
348
+ }
349
+ }).on('error', async (e) => {
350
+ await lCore.log(cctr, lText.stringifyJson(e.stack).slice(1, -1), '-error');
351
+ }).on('close', async () => {
352
+ try {
353
+ await cctr['onClose']();
354
+ }
355
+ catch (e) {
356
+ await lCore.log(cctr, lText.stringifyJson(e.stack).slice(1, -1), '-error');
357
+ }
358
+ resolve();
359
+ });
360
+ });
361
+ return true;
362
+ }
363
+ if (!wsSocket.ended) {
364
+ wsSocket.end();
365
+ }
366
+ return true;
367
+ }
368
+ if (!data.res) {
369
+ return true;
370
+ }
371
+ const middleCtr = (await Promise.resolve(`${config.const.ctrPath + 'middle'}`).then(s => __importStar(require(s)))).default;
372
+ const middle = new middleCtr(config, data.req, data.res);
373
+ let cctr = null;
374
+ if (data.timer) {
375
+ middle.setPrototype('_timer', data.timer);
376
+ }
377
+ middle.setPrototype('_param', param);
378
+ middle.setPrototype('_action', pathRight);
379
+ middle.setPrototype('_headers', headers);
380
+ middle.setPrototype('_get', get);
381
+ const rawPost = await getPost(data.req);
382
+ middle.setPrototype('_rawPost', rawPost[1]);
383
+ middle.setPrototype('_input', rawPost[0]);
384
+ const post = Object.assign({}, rawPost[1]);
385
+ trimPost(post);
386
+ middle.setPrototype('_post', post);
387
+ try {
388
+ rtn = await middle.onLoad();
389
+ }
390
+ catch (e) {
391
+ await lCore.log(middle, '(E03)' + lText.stringifyJson(e.stack).slice(1, -1), '-error');
392
+ data.res.setHeader('content-type', 'text/html; charset=utf-8');
393
+ data.res.setHeader('content-length', 25);
394
+ data.res.writeHead(500);
395
+ data.res.end('<h1>500 Server Error</h1><hr>Kebab');
396
+ return true;
397
+ }
398
+ let cacheTTL = middle.getPrototype('_cacheTTL');
399
+ let httpCode = middle.getPrototype('_httpCode');
400
+ if (rtn === undefined || rtn === true) {
401
+ const filePath = config.const.ctrPath + pathLeft + '.js';
402
+ if (!await lFs.isFile(filePath)) {
403
+ const text = '[Error] Controller not found, path: ' + path + '.';
404
+ if (config.route['#404']) {
405
+ data.res.setHeader('location', lText.urlResolve(config.const.urlBase, config.route['#404']));
406
+ data.res.writeHead(302);
407
+ data.res.end('');
408
+ return true;
409
+ }
410
+ data.res.setHeader('content-type', 'text/html; charset=utf-8');
411
+ data.res.setHeader('content-length', Buffer.byteLength(text));
412
+ data.res.writeHead(404);
413
+ data.res.end(text);
414
+ return true;
415
+ }
416
+ const ctrCtr = (await Promise.resolve(`${filePath}`).then(s => __importStar(require(s)))).default;
417
+ cctr = new ctrCtr(config, data.req, data.res ?? data.socket);
418
+ cctr.setPrototype('_timer', middle.getPrototype('_timer'));
419
+ cctr.setPrototype('_waitInfo', middle.getPrototype('_waitInfo'));
420
+ cctr.setPrototype('_param', param);
421
+ cctr.setPrototype('_action', middle.getPrototype('_action'));
422
+ cctr.setPrototype('_headers', headers);
423
+ cctr.setPrototype('_get', get);
424
+ cctr.setPrototype('_rawPost', middle.getPrototype('_rawPost'));
425
+ cctr.setPrototype('_input', middle.getPrototype('_input'));
426
+ cctr.setPrototype('_files', middle.getPrototype('_files'));
427
+ cctr.setPrototype('_post', middle.getPrototype('_post'));
428
+ cctr.setPrototype('_cookie', cookies);
429
+ cctr.setPrototype('_jwt', middle.getPrototype('_jwt'));
430
+ if (!cctr.getPrototype('_sess') && middle.getPrototype('_sess')) {
431
+ cctr.setPrototype('_session', middle.getPrototype('_session'));
432
+ cctr.setPrototype('_sess', middle.getPrototype('_sess'));
433
+ }
434
+ cctr.setPrototype('_cacheTTL', middle.getPrototype('_cacheTTL'));
435
+ cctr.setPrototype('_xsrf', middle.getPrototype('_xsrf'));
436
+ cctr.setPrototype('_httpCode', middle.getPrototype('_httpCode'));
437
+ await lCore.log(cctr, '', '-visit');
438
+ if (config.set.mustHttps && !config.const.https) {
439
+ data.res.setHeader('location', data.req.url ?? '');
440
+ data.res.writeHead(302);
441
+ return true;
442
+ }
443
+ if (pathRight.startsWith('_') || pathRight === 'onUpgrade' || pathRight === 'onLoad' || pathRight === 'onData' || pathRight === 'onDrain' || pathRight === 'onClose' || pathRight === 'setPrototype' || pathRight === 'getPrototype' || pathRight === 'getAuthorization') {
444
+ if (config.route['#404']) {
445
+ data.res.setHeader('location', lText.urlResolve(config.const.urlBase, config.route['#404']));
446
+ data.res.writeHead(302);
447
+ data.res.end('');
448
+ return true;
449
+ }
450
+ const text = '[Error] Action not found, path: ' + path + '.';
451
+ data.res.setHeader('content-type', 'text/html; charset=utf-8');
452
+ data.res.setHeader('content-length', Buffer.byteLength(text));
453
+ data.res.writeHead(404);
454
+ data.res.end(text);
455
+ return true;
456
+ }
457
+ pathRight = pathRight.replace(/-([a-zA-Z0-9])/g, function (t, t1) {
458
+ return t1.toUpperCase();
459
+ });
460
+ if (cctr[pathRight] === undefined) {
461
+ if (config.route['#404']) {
462
+ data.res.setHeader('location', lText.urlResolve(config.const.urlBase, config.route['#404']));
463
+ data.res.writeHead(302);
464
+ data.res.end('');
465
+ return true;
466
+ }
467
+ const text = '[Error] Action not found, path: ' + path + '.';
468
+ data.res.setHeader('content-type', 'text/html; charset=utf-8');
469
+ data.res.setHeader('content-length', Buffer.byteLength(text));
470
+ data.res.writeHead(404);
471
+ data.res.end(text);
472
+ return true;
473
+ }
474
+ try {
475
+ rtn = await cctr.onLoad();
476
+ if (rtn === undefined || rtn === true) {
477
+ rtn = await cctr[pathRight]();
478
+ rtn = await cctr.onUnload(rtn);
479
+ rtn = await middle.onUnload(rtn);
480
+ const sess = cctr.getPrototype('_sess');
481
+ if (sess) {
482
+ await sess.update();
483
+ }
484
+ }
485
+ cacheTTL = cctr.getPrototype('_cacheTTL');
486
+ httpCode = cctr.getPrototype('_httpCode');
487
+ }
488
+ catch (e) {
489
+ await lCore.log(cctr, '(E04)' + lText.stringifyJson(e.stack).slice(1, -1), '-error');
490
+ data.res.setHeader('content-type', 'text/html; charset=utf-8');
491
+ data.res.setHeader('content-length', 25);
492
+ data.res.writeHead(500);
493
+ data.res.end('<h1>500 Server Error</h1><hr>Kebab');
494
+ await waitCtr(cctr);
495
+ return true;
496
+ }
497
+ }
498
+ if (!data.res.headersSent && (cacheTTL > 0)) {
499
+ data.res.setHeader('expires', lTime.format(0, 'D, d M Y H:i:s', Date.now() + cacheTTL * 1000) + ' GMT');
500
+ data.res.setHeader('cache-control', 'max-age=' + cacheTTL.toString());
501
+ }
502
+ if (httpCode === 0) {
503
+ httpCode = 200;
504
+ }
505
+ if (rtn === undefined || typeof rtn === 'boolean' || rtn === null) {
506
+ if (data.res.headersSent) {
507
+ }
508
+ else {
509
+ if (data.res.getHeader('location')) {
510
+ data.res.writeHead(302);
511
+ }
512
+ else {
513
+ data.res.writeHead(httpCode);
514
+ }
515
+ }
516
+ if (!data.res.writableEnded) {
517
+ data.res.end('');
518
+ }
519
+ await waitCtr(cctr ?? middle);
520
+ return true;
521
+ }
522
+ if (typeof rtn === 'string' || rtn instanceof Buffer) {
523
+ let compress = null;
524
+ if (!data.res.headersSent) {
525
+ if (!data.res.getHeader('content-type')) {
526
+ data.res.setHeader('content-type', 'text/html; charset=utf-8');
527
+ }
528
+ if (Buffer.byteLength(rtn) >= 1024) {
529
+ compress = lZlib.createCompress(data.req.headers['accept-encoding'] ?? '');
530
+ if (compress) {
531
+ data.res.setHeader('content-encoding', compress.type);
532
+ }
533
+ }
534
+ data.res.writeHead(httpCode);
535
+ }
536
+ if (!data.res.writableEnded) {
537
+ if (compress) {
538
+ compress.compress.write(rtn);
539
+ compress.compress.pipe(data.res);
540
+ compress.compress.end();
541
+ }
542
+ else {
543
+ data.res.end(rtn);
544
+ }
545
+ }
546
+ }
547
+ else if (rtn instanceof stream.Readable || rtn instanceof lResponse.Response) {
548
+ const stm = rtn instanceof stream.Readable ? rtn : rtn.getStream();
549
+ let compress = null;
550
+ if (!data.res.headersSent) {
551
+ if (!data.res.getHeader('content-type')) {
552
+ data.res.setHeader('content-type', 'text/html; charset=utf-8');
553
+ }
554
+ compress = lZlib.createCompress(data.req.headers['accept-encoding'] ?? '');
555
+ if (compress) {
556
+ data.res.setHeader('content-encoding', compress.type);
557
+ }
558
+ data.res.writeHead(httpCode);
559
+ }
560
+ if (!data.res.writableEnded) {
561
+ if (compress) {
562
+ stm.pipe(compress.compress).pipe(data.res);
563
+ }
564
+ else {
565
+ stm.pipe(data.res);
566
+ }
567
+ }
568
+ }
569
+ else if (typeof rtn === 'object') {
570
+ if (Array.isArray(rtn)) {
571
+ if (rtn.length === 0) {
572
+ if (!data.res.headersSent) {
573
+ data.res.writeHead(500);
574
+ }
575
+ if (!data.res.writableEnded) {
576
+ data.res.end('<h1>500 Internal server error</h1><hr>Kebab');
577
+ }
578
+ }
579
+ else {
580
+ if (typeof rtn[0] === 'number') {
581
+ const json = { 'result': rtn[0] };
582
+ if (rtn[1] !== undefined) {
583
+ if (typeof rtn[1] === 'object') {
584
+ for (let i = 1; i < rtn.length; ++i) {
585
+ Object.assign(json, rtn[i]);
586
+ }
587
+ }
588
+ else {
589
+ json['msg'] = rtn[1];
590
+ for (let i = 2; i < rtn.length; ++i) {
591
+ Object.assign(json, rtn[i]);
592
+ }
593
+ }
594
+ }
595
+ const writeData = lText.stringifyJson(json);
596
+ let compress = null;
597
+ if (!data.res.headersSent) {
598
+ data.res.setHeader('content-type', 'application/json; charset=utf-8');
599
+ if (Buffer.byteLength(writeData) >= 1024) {
600
+ compress = lZlib.createCompress(data.req.headers['accept-encoding'] ?? '');
601
+ if (compress) {
602
+ data.res.setHeader('content-encoding', compress.type);
603
+ }
604
+ }
605
+ data.res.writeHead(httpCode);
606
+ }
607
+ if (!data.res.writableEnded) {
608
+ if (compress) {
609
+ compress.compress.write(writeData);
610
+ compress.compress.pipe(data.res);
611
+ compress.compress.end();
612
+ }
613
+ else {
614
+ data.res.end(writeData);
615
+ }
616
+ }
617
+ }
618
+ else {
619
+ let compress = null;
620
+ if (!data.res.headersSent) {
621
+ if (!data.res.getHeader('content-type')) {
622
+ data.res.setHeader('content-type', 'text/html; charset=utf-8');
623
+ }
624
+ compress = lZlib.createCompress(data.req.headers['accept-encoding'] ?? '');
625
+ if (compress) {
626
+ data.res.setHeader('content-encoding', compress.type);
627
+ }
628
+ data.res.writeHead(httpCode);
629
+ }
630
+ if (!data.res.writableEnded) {
631
+ const passThrough = new stream.PassThrough();
632
+ if (compress) {
633
+ passThrough.pipe(compress.compress).pipe(data.res);
634
+ }
635
+ else {
636
+ passThrough.pipe(data.res);
637
+ }
638
+ await lCore.passThroughAppend(passThrough, rtn);
639
+ }
640
+ }
641
+ }
642
+ }
643
+ else {
644
+ const writeData = lText.stringifyJson(rtn);
645
+ let compress = null;
646
+ if (!data.res.headersSent) {
647
+ data.res.setHeader('content-type', 'application/json; charset=utf-8');
648
+ if (Buffer.byteLength(writeData) >= 1024) {
649
+ compress = lZlib.createCompress(data.req.headers['accept-encoding'] ?? '');
650
+ if (compress) {
651
+ data.res.setHeader('content-encoding', compress.type);
652
+ }
653
+ }
654
+ data.res.writeHead(httpCode);
655
+ }
656
+ if (!data.res.writableEnded) {
657
+ if (compress) {
658
+ compress.compress.write(writeData);
659
+ compress.compress.pipe(data.res);
660
+ compress.compress.end();
661
+ }
662
+ else {
663
+ data.res.end(writeData);
664
+ }
665
+ }
666
+ }
667
+ }
668
+ else {
669
+ if (!data.res.headersSent) {
670
+ data.res.writeHead(500);
671
+ }
672
+ if (!data.res.writableEnded) {
673
+ data.res.end('<h1>500 Internal server error</h1><hr>Kebab');
674
+ }
675
+ }
676
+ await waitCtr(cctr ?? middle);
677
+ return true;
678
+ }
679
+ function getPathLeftRight(path) {
680
+ const pathLio = path.lastIndexOf('/');
681
+ if (pathLio === -1) {
682
+ return [path, 'index'];
683
+ }
684
+ const right = path.slice(pathLio + 1);
685
+ return [path.slice(0, pathLio), right === '' ? 'index' : right];
686
+ }
687
+ function getWsCtrName(path) {
688
+ const pathLio = path.lastIndexOf('/');
689
+ if (pathLio === -1) {
690
+ return path.toLowerCase();
691
+ }
692
+ return path.slice(pathLio + 1).toLowerCase();
693
+ }
694
+ async function unlinkUploadFiles(cctr) {
695
+ const cfiles = cctr instanceof sCtr.Ctr ? cctr.getPrototype('_files') : cctr;
696
+ for (const name in cfiles) {
697
+ let files = cfiles[name];
698
+ if (!Array.isArray(files)) {
699
+ files = [files];
700
+ }
701
+ for (const file of files) {
702
+ await lFs.unlink(file.path);
703
+ }
704
+ }
705
+ }
706
+ async function waitCtr(cctr) {
707
+ const waitInfo = cctr.getPrototype('_waitInfo');
708
+ if (waitInfo.asyncTask.count) {
709
+ await waitInfo.asyncTask.callback();
710
+ }
711
+ if (waitInfo.transaction) {
712
+ const msg = 'transaction(' + waitInfo.transaction + ') not be closed';
713
+ lCore.display('[ERROR][ROUTE][WAITCTR] ' + msg + ': ', cctr.getPrototype('_config').const.path);
714
+ await lCore.log(cctr, msg, '-error');
715
+ }
716
+ await unlinkUploadFiles(cctr);
717
+ }
718
+ function trimPost(post) {
719
+ for (const key in post) {
720
+ const val = post[key];
721
+ if (typeof val === 'string') {
722
+ post[key] = post[key].trim();
723
+ }
724
+ else if (typeof val === 'object') {
725
+ trimPost(post[key]);
726
+ }
727
+ }
728
+ }
729
+ function getPost(req) {
730
+ return new Promise(function (resolve) {
731
+ const ct = req.headers['content-type'] ?? '';
732
+ if (ct.includes('form-data')) {
733
+ resolve(['', {}]);
734
+ return;
735
+ }
736
+ let buffer = Buffer.from('');
737
+ req.on('data', function (chunk) {
738
+ buffer = Buffer.concat([buffer, chunk], buffer.length + chunk.length);
739
+ });
740
+ req.on('end', function () {
741
+ const s = buffer.toString();
742
+ if (!s) {
743
+ resolve(['', {}]);
744
+ return;
745
+ }
746
+ if (ct.includes('json')) {
747
+ try {
748
+ resolve([s, lText.parseJson(s)]);
749
+ }
750
+ catch {
751
+ resolve(['', {}]);
752
+ }
753
+ return;
754
+ }
755
+ resolve([s, lText.queryParse(s)]);
756
+ });
757
+ });
758
+ }
759
+ function getFormData(req, events = {}) {
760
+ return new Promise(function (resolve) {
761
+ const ct = req.headers['content-type'] ?? '';
762
+ if (!ct) {
763
+ resolve({ 'post': {}, 'files': {} });
764
+ return;
765
+ }
766
+ const clio = ct.lastIndexOf('boundary=');
767
+ if (clio === -1) {
768
+ resolve({ 'post': {}, 'files': {} });
769
+ return;
770
+ }
771
+ const rtn = {
772
+ 'post': {},
773
+ 'files': {}
774
+ };
775
+ const boundary = ct.slice(clio + 9);
776
+ let buffer = Buffer.from('');
777
+ let EState;
778
+ (function (EState) {
779
+ EState[EState["WAIT"] = 0] = "WAIT";
780
+ EState[EState["FILE"] = 1] = "FILE";
781
+ EState[EState["POST"] = 2] = "POST";
782
+ })(EState || (EState = {}));
783
+ let state = EState.WAIT;
784
+ let name = '';
785
+ let fileName = '';
786
+ let ftmpName = '';
787
+ let ftmpStream;
788
+ let ftmpSize = 0;
789
+ let writeFileLength = 0;
790
+ let readEnd = false;
791
+ req.on('data', function (chunk) {
792
+ buffer = Buffer.concat([buffer, chunk], buffer.length + chunk.length);
793
+ while (true) {
794
+ switch (state) {
795
+ case EState.WAIT: {
796
+ const io = buffer.indexOf('\r\n\r\n');
797
+ if (io === -1) {
798
+ return;
799
+ }
800
+ const head = buffer.subarray(0, io).toString();
801
+ buffer = buffer.subarray(io + 4);
802
+ let match = /name="(.+?)"/.exec(head);
803
+ name = match ? match[1] : '';
804
+ match = /filename="(.+?)"/.exec(head);
805
+ if (!match) {
806
+ state = EState.POST;
807
+ }
808
+ else {
809
+ ++writeFileLength;
810
+ state = EState.FILE;
811
+ fileName = match[1];
812
+ const fr = events.onfilestart?.(name);
813
+ if (fr !== true) {
814
+ const date = new Date();
815
+ ftmpName = date.getUTCFullYear().toString() +
816
+ (date.getUTCMonth() + 1).toString().padStart(2, '0') +
817
+ date.getUTCDate().toString().padStart(2, '0') +
818
+ date.getUTCHours().toString().padStart(2, '0') +
819
+ date.getUTCMinutes().toString().padStart(2, '0') + '_' + lCore.random() + '.ftmp';
820
+ ftmpStream = lFs.createWriteStream(kebab.FTMP_CWD + ftmpName);
821
+ ftmpSize = 0;
822
+ }
823
+ else {
824
+ ftmpName = '';
825
+ }
826
+ }
827
+ break;
828
+ }
829
+ case EState.POST: {
830
+ const io = buffer.indexOf('\r\n--' + boundary);
831
+ if (io === -1) {
832
+ return;
833
+ }
834
+ const val = buffer.subarray(0, io).toString();
835
+ if (rtn.post[name]) {
836
+ if (Array.isArray(rtn.post[name])) {
837
+ rtn.post[name].push(val);
838
+ }
839
+ else {
840
+ rtn.post[name] = [rtn.post[name], val];
841
+ }
842
+ }
843
+ else {
844
+ rtn.post[name] = val;
845
+ }
846
+ state = EState.WAIT;
847
+ buffer = buffer.subarray(io + 4 + boundary.length);
848
+ break;
849
+ }
850
+ case EState.FILE: {
851
+ const io = buffer.indexOf('\r\n--' + boundary);
852
+ if (io === -1) {
853
+ const writeBuffer = buffer.subarray(0, -boundary.length - 4);
854
+ if (ftmpName === '') {
855
+ events.onfiledata?.(writeBuffer);
856
+ }
857
+ else {
858
+ ftmpStream.write(writeBuffer);
859
+ ftmpSize += Buffer.byteLength(writeBuffer);
860
+ }
861
+ buffer = buffer.subarray(-boundary.length - 4);
862
+ return;
863
+ }
864
+ const writeBuffer = buffer.subarray(0, io);
865
+ if (ftmpName === '') {
866
+ events.onfileend?.();
867
+ }
868
+ else {
869
+ ftmpStream.write(writeBuffer);
870
+ ftmpSize += Buffer.byteLength(writeBuffer);
871
+ ftmpStream.end(() => {
872
+ --writeFileLength;
873
+ if (!readEnd) {
874
+ return;
875
+ }
876
+ if (writeFileLength) {
877
+ return;
878
+ }
879
+ resolve(rtn);
880
+ });
881
+ let fname = fileName.replace(/\\/g, '/');
882
+ const nlio = fname.lastIndexOf('/');
883
+ if (nlio !== -1) {
884
+ fname = fname.slice(nlio + 1);
885
+ }
886
+ const val = {
887
+ 'name': fname,
888
+ 'origin': fileName,
889
+ 'size': ftmpSize,
890
+ 'path': kebab.FTMP_CWD + ftmpName
891
+ };
892
+ if (rtn.files[name]) {
893
+ if (Array.isArray(rtn.files[name])) {
894
+ rtn.files[name].push(val);
895
+ }
896
+ else {
897
+ rtn.files[name] = [rtn.files[name], val];
898
+ }
899
+ }
900
+ else {
901
+ rtn.files[name] = val;
902
+ }
903
+ }
904
+ state = EState.WAIT;
905
+ buffer = buffer.subarray(io + 4 + boundary.length);
906
+ break;
907
+ }
908
+ }
909
+ }
910
+ });
911
+ req.on('error', function () {
912
+ resolve(false);
913
+ });
914
+ req.on('end', function () {
915
+ readEnd = true;
916
+ if (writeFileLength) {
917
+ return;
918
+ }
919
+ resolve(rtn);
920
+ });
921
+ });
922
+ }