tspace-spear 1.2.2 → 1.2.4
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.
- package/README.md +304 -23
- package/dist/lib/core/const/index.d.ts +153 -0
- package/dist/lib/core/const/index.js +105 -0
- package/dist/lib/core/const/index.js.map +1 -0
- package/dist/lib/core/decorators/context.d.ts +16 -9
- package/dist/lib/core/decorators/context.js +85 -59
- package/dist/lib/core/decorators/context.js.map +1 -1
- package/dist/lib/core/decorators/headers.d.ts +2 -2
- package/dist/lib/core/decorators/headers.js +1 -1
- package/dist/lib/core/decorators/headers.js.map +1 -1
- package/dist/lib/core/decorators/methods.d.ts +7 -7
- package/dist/lib/core/decorators/methods.js.map +1 -1
- package/dist/lib/core/decorators/middleware.d.ts +3 -3
- package/dist/lib/core/decorators/middleware.js +2 -2
- package/dist/lib/core/decorators/middleware.js.map +1 -1
- package/dist/lib/core/decorators/statusCode.d.ts +1 -1
- package/dist/lib/core/decorators/statusCode.js.map +1 -1
- package/dist/lib/core/decorators/swagger.d.ts +1 -1
- package/dist/lib/core/decorators/swagger.js.map +1 -1
- package/dist/lib/core/server/express.d.ts +295 -0
- package/dist/lib/core/server/express.js +1356 -0
- package/dist/lib/core/server/express.js.map +1 -0
- package/dist/lib/core/server/fast-router.d.ts +133 -0
- package/dist/lib/core/server/fast-router.js +277 -0
- package/dist/lib/core/server/fast-router.js.map +1 -0
- package/dist/lib/core/server/index.d.ts +43 -36
- package/dist/lib/core/server/index.js +300 -426
- package/dist/lib/core/server/index.js.map +1 -1
- package/dist/lib/core/server/net/index.d.ts +20 -0
- package/dist/lib/core/server/net/index.js +393 -0
- package/dist/lib/core/server/net/index.js.map +1 -0
- package/dist/lib/core/server/parser-factory.d.ts +20 -12
- package/dist/lib/core/server/parser-factory.js +283 -196
- package/dist/lib/core/server/parser-factory.js.map +1 -1
- package/dist/lib/core/server/request.d.ts +2 -0
- package/dist/lib/core/server/request.js +7 -0
- package/dist/lib/core/server/request.js.map +1 -0
- package/dist/lib/core/server/response.d.ts +6 -0
- package/dist/lib/core/server/response.js +168 -0
- package/dist/lib/core/server/response.js.map +1 -0
- package/dist/lib/core/server/router.d.ts +2 -2
- package/dist/lib/core/server/router.js +2 -1
- package/dist/lib/core/server/router.js.map +1 -1
- package/dist/lib/core/server/uWS/index.d.ts +30 -0
- package/dist/lib/core/server/uWS/index.js +357 -0
- package/dist/lib/core/server/uWS/index.js.map +1 -0
- package/dist/lib/core/types/index.d.ts +159 -38
- package/dist/lib/core/utils/index.d.ts +12 -0
- package/dist/lib/core/utils/index.js +137 -0
- package/dist/lib/core/utils/index.js.map +1 -0
- package/dist/lib/index.d.ts +3 -3
- package/dist/lib/index.js +3 -2
- package/dist/lib/index.js.map +1 -1
- package/package.json +27 -11
- package/dist/tests/benchmark.test.d.ts +0 -1
- package/dist/tests/benchmark.test.js +0 -145
- package/dist/tests/benchmark.test.js.map +0 -1
|
@@ -38,15 +38,20 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
38
38
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
39
|
exports.Spear = exports.Application = void 0;
|
|
40
40
|
const http_1 = __importStar(require("http"));
|
|
41
|
-
const
|
|
41
|
+
const const_1 = require("../const");
|
|
42
|
+
const stream_1 = require("stream");
|
|
42
43
|
const cluster_1 = __importDefault(require("cluster"));
|
|
43
44
|
const os_1 = __importDefault(require("os"));
|
|
44
45
|
const fs_1 = __importDefault(require("fs"));
|
|
45
46
|
const path_1 = __importDefault(require("path"));
|
|
46
|
-
const url_1 = require("url");
|
|
47
47
|
const on_finished_1 = __importDefault(require("on-finished"));
|
|
48
48
|
const ws_1 = __importDefault(require("ws"));
|
|
49
|
+
const net_1 = __importDefault(require("net"));
|
|
49
50
|
const parser_factory_1 = require("./parser-factory");
|
|
51
|
+
const fast_router_1 = require("./fast-router");
|
|
52
|
+
const response_1 = require("./response");
|
|
53
|
+
const uWS_1 = require("./uWS");
|
|
54
|
+
const net_2 = require("./net");
|
|
50
55
|
/**
|
|
51
56
|
*
|
|
52
57
|
* The 'Spear' class is used to create a server and handle HTTP requests.
|
|
@@ -66,9 +71,10 @@ const parser_factory_1 = require("./parser-factory");
|
|
|
66
71
|
class Spear {
|
|
67
72
|
_controllers;
|
|
68
73
|
_middlewares;
|
|
69
|
-
|
|
70
|
-
_router = (0, find_my_way_1.default)();
|
|
74
|
+
_router = new fast_router_1.FastRouter();
|
|
71
75
|
_parser = new parser_factory_1.ParserFactory();
|
|
76
|
+
_globalPrefix = '';
|
|
77
|
+
_adapter = { kind: 'http', server: http_1.default };
|
|
72
78
|
_cluster;
|
|
73
79
|
_cors;
|
|
74
80
|
_swagger = {
|
|
@@ -76,7 +82,7 @@ class Spear {
|
|
|
76
82
|
path: '/api/docs',
|
|
77
83
|
servers: [
|
|
78
84
|
{
|
|
79
|
-
url: '
|
|
85
|
+
url: '/'
|
|
80
86
|
}
|
|
81
87
|
],
|
|
82
88
|
tags: [],
|
|
@@ -87,9 +93,11 @@ class Spear {
|
|
|
87
93
|
}
|
|
88
94
|
};
|
|
89
95
|
_swaggerSpecs = [];
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
96
|
+
_ws = {
|
|
97
|
+
handler: null,
|
|
98
|
+
server: null,
|
|
99
|
+
options: null
|
|
100
|
+
};
|
|
93
101
|
_errorHandler = null;
|
|
94
102
|
_globalMiddlewares = [];
|
|
95
103
|
_formatResponse = null;
|
|
@@ -102,14 +110,17 @@ class Spear {
|
|
|
102
110
|
ms: 1000 * 60 * 10
|
|
103
111
|
}
|
|
104
112
|
};
|
|
105
|
-
constructor({ controllers, middlewares, globalPrefix, logger, cluster } = {}) {
|
|
113
|
+
constructor({ controllers, middlewares, globalPrefix, logger, cluster, adapter } = {}) {
|
|
114
|
+
this._controllers = controllers;
|
|
115
|
+
this._middlewares = middlewares;
|
|
106
116
|
if (logger)
|
|
107
117
|
this.useLogger();
|
|
108
118
|
if (cluster)
|
|
109
119
|
this.useCluster(cluster);
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
120
|
+
if (adapter)
|
|
121
|
+
this.useAdater(adapter);
|
|
122
|
+
if (globalPrefix)
|
|
123
|
+
this.useGlobalPrefix(globalPrefix);
|
|
113
124
|
}
|
|
114
125
|
/**
|
|
115
126
|
* The get 'instance' method is used to get the instance of Spear.
|
|
@@ -122,7 +133,7 @@ class Spear {
|
|
|
122
133
|
/**
|
|
123
134
|
* The get 'routers' method is used get the all routers.
|
|
124
135
|
*
|
|
125
|
-
* @returns {
|
|
136
|
+
* @returns {FastRouter}
|
|
126
137
|
*/
|
|
127
138
|
get routers() {
|
|
128
139
|
return this._router;
|
|
@@ -135,8 +146,8 @@ class Spear {
|
|
|
135
146
|
* @returns {this}
|
|
136
147
|
*/
|
|
137
148
|
ws(handlers, options) {
|
|
138
|
-
this._ws = handlers();
|
|
139
|
-
this.
|
|
149
|
+
this._ws.handler = handlers();
|
|
150
|
+
this._ws.options = options ?? {};
|
|
140
151
|
return this;
|
|
141
152
|
}
|
|
142
153
|
/**
|
|
@@ -151,6 +162,40 @@ class Spear {
|
|
|
151
162
|
this._globalMiddlewares.push(middleware);
|
|
152
163
|
return this;
|
|
153
164
|
}
|
|
165
|
+
/**
|
|
166
|
+
* The 'useGlobalPrefix' method is used to sets a global prefix for all routes in the router.
|
|
167
|
+
*
|
|
168
|
+
* If `globalPrefix` is `null` or `undefined`, it will default to an empty string,
|
|
169
|
+
* meaning no prefix will be applied.
|
|
170
|
+
*
|
|
171
|
+
* @param {string | null} globalPrefix - The base path prefix to apply to all routes.
|
|
172
|
+
* @returns {this} Returns the current instance for method chaining.
|
|
173
|
+
*/
|
|
174
|
+
useGlobalPrefix(globalPrefix) {
|
|
175
|
+
this._globalPrefix = globalPrefix == null ? '' : globalPrefix;
|
|
176
|
+
return this;
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* The 'useAdater' method is used to switch between different server implementations,
|
|
180
|
+
* such as the native Node.js HTTP server or uWebSockets.js (uWS).
|
|
181
|
+
*
|
|
182
|
+
* @param {T.AdapterServer} adapter - The adapter instance (e.g., HTTP or uWS).
|
|
183
|
+
* @returns {this} Returns the current instance for chaining
|
|
184
|
+
*/
|
|
185
|
+
useAdater(adapter) {
|
|
186
|
+
if (adapter === http_1.default) {
|
|
187
|
+
this._adapter = { kind: 'http', server: adapter };
|
|
188
|
+
}
|
|
189
|
+
else if (adapter === net_1.default) {
|
|
190
|
+
this._adapter = { kind: 'net', server: adapter };
|
|
191
|
+
}
|
|
192
|
+
else {
|
|
193
|
+
//@ts-ignore
|
|
194
|
+
this._adapter = { kind: 'uWS', server: adapter };
|
|
195
|
+
}
|
|
196
|
+
this._parser.useAdater(this._adapter);
|
|
197
|
+
return this;
|
|
198
|
+
}
|
|
154
199
|
/**
|
|
155
200
|
* The 'useCluster' method is used cluster run the server
|
|
156
201
|
*
|
|
@@ -187,13 +232,13 @@ class Spear {
|
|
|
187
232
|
? `\x1b[32m${statusCode}\x1b[0m`
|
|
188
233
|
: `\x1b[31m${statusCode}\x1b[0m`;
|
|
189
234
|
};
|
|
190
|
-
if (exceptPath instanceof RegExp && exceptPath.test(
|
|
235
|
+
if (exceptPath instanceof RegExp && exceptPath.test(req.url))
|
|
191
236
|
return next();
|
|
192
|
-
if (Array.isArray(exceptPath) && exceptPath.some(v =>
|
|
237
|
+
if (Array.isArray(exceptPath) && exceptPath.some(v => req.url === v))
|
|
193
238
|
return next();
|
|
194
239
|
if (methods != null &&
|
|
195
240
|
methods.length &&
|
|
196
|
-
!methods.some(v => v.
|
|
241
|
+
!methods.some(v => v.toLowerCase() === req.method.toLowerCase())) {
|
|
197
242
|
return next();
|
|
198
243
|
}
|
|
199
244
|
const startTime = process.hrtime();
|
|
@@ -202,7 +247,7 @@ class Spear {
|
|
|
202
247
|
`[\x1b[1m\x1b[34mINFO\x1b[0m]`,
|
|
203
248
|
`\x1b[34m${new Date().toJSON()}\x1b[0m`,
|
|
204
249
|
`\x1b[33m${req.method}\x1b[0m`,
|
|
205
|
-
`${decodeURIComponent(
|
|
250
|
+
`${decodeURIComponent(req.url)}`,
|
|
206
251
|
`${statusCode(res)}`,
|
|
207
252
|
`${diffTime(startTime)}`,
|
|
208
253
|
].join(" "));
|
|
@@ -219,29 +264,26 @@ class Spear {
|
|
|
219
264
|
*/
|
|
220
265
|
useBodyParser({ except } = {}) {
|
|
221
266
|
this._globalMiddlewares.push((ctx, next) => {
|
|
222
|
-
const { req } = ctx;
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
const isCanParserBody = contentType.includes('application/json') ||
|
|
226
|
-
contentType.includes('application/x-www-form-urlencoded');
|
|
227
|
-
if (except != null &&
|
|
228
|
-
Array.isArray(except) &&
|
|
229
|
-
except.some(v => v.toLocaleLowerCase() === (req.method)?.toLocaleLowerCase())) {
|
|
267
|
+
const { req, res } = ctx;
|
|
268
|
+
if (Array.isArray(except) &&
|
|
269
|
+
except.some(v => v.toLowerCase() === (req.method).toLowerCase())) {
|
|
230
270
|
return next();
|
|
231
271
|
}
|
|
232
|
-
|
|
272
|
+
const contentType = req?.headers['content-type'] ?? null;
|
|
273
|
+
if (contentType == null)
|
|
233
274
|
return next();
|
|
234
|
-
|
|
275
|
+
const isFileUpload = contentType && contentType.startsWith('multipart/form-data');
|
|
276
|
+
if (isFileUpload)
|
|
235
277
|
return next();
|
|
236
278
|
if (req?.body != null)
|
|
237
279
|
return next();
|
|
238
|
-
Promise.resolve(this._parser.body(req))
|
|
239
|
-
.then(
|
|
240
|
-
req.body =
|
|
280
|
+
Promise.resolve(this._parser.body(req, res))
|
|
281
|
+
.then(body => {
|
|
282
|
+
req.body = body;
|
|
241
283
|
return next();
|
|
242
284
|
})
|
|
243
285
|
.catch(err => {
|
|
244
|
-
return this.
|
|
286
|
+
return this._nextError(ctx)(err);
|
|
245
287
|
});
|
|
246
288
|
});
|
|
247
289
|
return this;
|
|
@@ -250,11 +292,11 @@ class Spear {
|
|
|
250
292
|
* The 'useFileUpload' method is a middleware used to handler file uploads. It adds a file upload of incoming HTTP requests.
|
|
251
293
|
*
|
|
252
294
|
* @param {?Object}
|
|
253
|
-
* @property {?number} limits
|
|
295
|
+
* @property {?number} limits // bytes. default Infinity
|
|
254
296
|
* @property {?string} tempFileDir
|
|
255
297
|
* @property {?Object} removeTempFile
|
|
256
298
|
* @property {boolean} removeTempFile.remove
|
|
257
|
-
* @property {number}
|
|
299
|
+
* @property {number} removeTempFile.ms
|
|
258
300
|
* @returns
|
|
259
301
|
*/
|
|
260
302
|
useFileUpload({ limit, tempFileDir, removeTempFile } = {}) {
|
|
@@ -268,7 +310,7 @@ class Spear {
|
|
|
268
310
|
this._fileUploadOptions.removeTempFile = removeTempFile;
|
|
269
311
|
}
|
|
270
312
|
this._globalMiddlewares.push((ctx, next) => {
|
|
271
|
-
const { req } = ctx;
|
|
313
|
+
const { req, res } = ctx;
|
|
272
314
|
if (req.method === 'GET') {
|
|
273
315
|
return next();
|
|
274
316
|
}
|
|
@@ -279,14 +321,14 @@ class Spear {
|
|
|
279
321
|
if (req?.files != null)
|
|
280
322
|
return next();
|
|
281
323
|
Promise
|
|
282
|
-
.resolve(this._parser.files(req, this._fileUploadOptions))
|
|
324
|
+
.resolve(this._parser.files({ req, res, options: this._fileUploadOptions }))
|
|
283
325
|
.then(r => {
|
|
284
326
|
req.files = r.files;
|
|
285
327
|
req.body = r.body;
|
|
286
328
|
return next();
|
|
287
329
|
})
|
|
288
330
|
.catch(err => {
|
|
289
|
-
return this.
|
|
331
|
+
return this._nextError(ctx)(err);
|
|
290
332
|
});
|
|
291
333
|
});
|
|
292
334
|
return this;
|
|
@@ -359,6 +401,22 @@ class Spear {
|
|
|
359
401
|
});
|
|
360
402
|
return server;
|
|
361
403
|
}
|
|
404
|
+
if (this._adapter.kind === 'uWS') {
|
|
405
|
+
const handler = () => {
|
|
406
|
+
this._onListeners.forEach(listener => listener());
|
|
407
|
+
if (this._swagger.use) {
|
|
408
|
+
this._swaggerHandler();
|
|
409
|
+
}
|
|
410
|
+
callback?.({ server, port });
|
|
411
|
+
};
|
|
412
|
+
if (hostname) {
|
|
413
|
+
server.listen(port, String(hostname), handler);
|
|
414
|
+
}
|
|
415
|
+
else {
|
|
416
|
+
server.listen(port, handler);
|
|
417
|
+
}
|
|
418
|
+
return server;
|
|
419
|
+
}
|
|
362
420
|
const args = hostname
|
|
363
421
|
? [port, hostname, () => callback?.({ server, port: port })]
|
|
364
422
|
: [port, () => callback?.({ server, port: port })];
|
|
@@ -369,10 +427,6 @@ class Spear {
|
|
|
369
427
|
this._swaggerHandler();
|
|
370
428
|
}
|
|
371
429
|
});
|
|
372
|
-
server.on('error', (_) => {
|
|
373
|
-
port = Math.floor(Math.random() * 8999) + 1000;
|
|
374
|
-
server.listen(port);
|
|
375
|
-
});
|
|
376
430
|
return server;
|
|
377
431
|
}
|
|
378
432
|
/**
|
|
@@ -443,20 +497,10 @@ class Spear {
|
|
|
443
497
|
*/
|
|
444
498
|
notfound(fn) {
|
|
445
499
|
const handler = ({ req, res }) => {
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
res: this._customizeResponse(req, res),
|
|
449
|
-
headers: {},
|
|
450
|
-
query: {},
|
|
451
|
-
files: {},
|
|
452
|
-
body: {},
|
|
453
|
-
params: {},
|
|
454
|
-
cookies: {}
|
|
455
|
-
});
|
|
500
|
+
const ctx = this._createContext({ req, res, ps: {} });
|
|
501
|
+
return fn(ctx);
|
|
456
502
|
};
|
|
457
|
-
this.
|
|
458
|
-
return this.all('*', ...this._globalMiddlewares, handler);
|
|
459
|
-
});
|
|
503
|
+
this.all('*', handler);
|
|
460
504
|
return this;
|
|
461
505
|
}
|
|
462
506
|
/**
|
|
@@ -565,7 +609,7 @@ class Spear {
|
|
|
565
609
|
return this;
|
|
566
610
|
}
|
|
567
611
|
/**
|
|
568
|
-
* The '
|
|
612
|
+
* The 'all' method is used to add the request handler to the router for 'GET' 'POST' 'PUT' 'PATCH' 'DELETE' 'HEAD' 'OPTIONS' methods.
|
|
569
613
|
*
|
|
570
614
|
* @param {string} path
|
|
571
615
|
* @callback {...Function[]} handlers of the middlewares
|
|
@@ -573,58 +617,12 @@ class Spear {
|
|
|
573
617
|
* @property {function} next - go to next function
|
|
574
618
|
* @returns {this}
|
|
575
619
|
*/
|
|
576
|
-
any(path, ...handlers) {
|
|
577
|
-
this._onListeners.push(() => {
|
|
578
|
-
return this._router.all(this._normalizePath(this._globalPrefix, path), this._wrapHandlers(...this._globalMiddlewares, ...handlers));
|
|
579
|
-
});
|
|
580
|
-
return this;
|
|
581
|
-
}
|
|
582
|
-
/**
|
|
583
|
-
* The 'all' method is used to add the request handler to the router for 'GET' 'POST' 'PUT' 'PATCH' 'DELETE' 'HEAD' 'OPTIONS' methods.
|
|
584
|
-
*
|
|
585
|
-
* @param {string} path
|
|
586
|
-
* @callback {...Function[]} handlers of the middlewares
|
|
587
|
-
* @property {object} ctx - context { req , res , query , params , cookies , files , body}
|
|
588
|
-
* @property {function} next - go to next function
|
|
589
|
-
* @returns {this}
|
|
590
|
-
*/
|
|
591
620
|
all(path, ...handlers) {
|
|
592
621
|
this._onListeners.push(() => {
|
|
593
622
|
return this._router.all(this._normalizePath(this._globalPrefix, path), this._wrapHandlers(...this._globalMiddlewares, ...handlers));
|
|
594
623
|
});
|
|
595
624
|
return this;
|
|
596
625
|
}
|
|
597
|
-
_clusterMode({ server, port, hostname, callback }) {
|
|
598
|
-
if (cluster_1.default.isPrimary) {
|
|
599
|
-
const numCPUs = os_1.default.cpus().length;
|
|
600
|
-
const maxWorkers = typeof this._cluster === 'boolean' || this._cluster == null
|
|
601
|
-
? numCPUs
|
|
602
|
-
: this._cluster;
|
|
603
|
-
for (let i = 0; i < maxWorkers; i++) {
|
|
604
|
-
cluster_1.default.fork();
|
|
605
|
-
}
|
|
606
|
-
cluster_1.default.on('exit', () => {
|
|
607
|
-
cluster_1.default.fork();
|
|
608
|
-
});
|
|
609
|
-
}
|
|
610
|
-
if (cluster_1.default.isWorker) {
|
|
611
|
-
const args = hostname
|
|
612
|
-
? [port, hostname, () => callback?.({ server, port: port })]
|
|
613
|
-
: [port, () => callback?.({ server, port: port })];
|
|
614
|
-
server.listen(...args);
|
|
615
|
-
server.on('listening', () => {
|
|
616
|
-
this._onListeners.forEach(listener => listener());
|
|
617
|
-
if (this._swagger.use) {
|
|
618
|
-
this._swaggerHandler();
|
|
619
|
-
}
|
|
620
|
-
});
|
|
621
|
-
server.on('error', (_) => {
|
|
622
|
-
port = Math.floor(Math.random() * 8999) + 1000;
|
|
623
|
-
server.listen(port);
|
|
624
|
-
});
|
|
625
|
-
}
|
|
626
|
-
return;
|
|
627
|
-
}
|
|
628
626
|
async _import(dir, pattern) {
|
|
629
627
|
const directories = fs_1.default.readdirSync(dir, { withFileTypes: true });
|
|
630
628
|
const files = (await Promise.all(directories.map((directory) => {
|
|
@@ -738,382 +736,258 @@ class Spear {
|
|
|
738
736
|
}
|
|
739
737
|
return;
|
|
740
738
|
}
|
|
741
|
-
_customizeResponse(req, res) {
|
|
742
|
-
const response = res;
|
|
743
|
-
response.json = (results) => {
|
|
744
|
-
if (res.writableEnded)
|
|
745
|
-
return;
|
|
746
|
-
if (typeof results === 'string') {
|
|
747
|
-
if (!res.headersSent) {
|
|
748
|
-
res.writeHead(200, { 'Content-Type': 'text/plain' });
|
|
749
|
-
}
|
|
750
|
-
return res.end(results);
|
|
751
|
-
}
|
|
752
|
-
if (!res.headersSent) {
|
|
753
|
-
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
754
|
-
}
|
|
755
|
-
if (results == null) {
|
|
756
|
-
if (this._formatResponse != null) {
|
|
757
|
-
return res.end(JSON.stringify(this._formatResponse(null, res.statusCode), null, 2));
|
|
758
|
-
}
|
|
759
|
-
return res.end();
|
|
760
|
-
}
|
|
761
|
-
if (this._formatResponse != null) {
|
|
762
|
-
return res.end(JSON.stringify(this._formatResponse({
|
|
763
|
-
...results
|
|
764
|
-
}, res.statusCode), null, 2));
|
|
765
|
-
}
|
|
766
|
-
return res.end(JSON.stringify({
|
|
767
|
-
...results,
|
|
768
|
-
}, null, 2));
|
|
769
|
-
};
|
|
770
|
-
response.send = (results) => {
|
|
771
|
-
if (res.writableEnded)
|
|
772
|
-
return;
|
|
773
|
-
res.writeHead(res.statusCode, { 'Content-Type': 'text/plain' });
|
|
774
|
-
return res.end(results);
|
|
775
|
-
};
|
|
776
|
-
response.html = (results) => {
|
|
777
|
-
if (res.writableEnded)
|
|
778
|
-
return;
|
|
779
|
-
res.writeHead(res.statusCode, { 'Content-Type': 'text/html' });
|
|
780
|
-
return res.end(results);
|
|
781
|
-
};
|
|
782
|
-
response.error = (err) => {
|
|
783
|
-
const statusCandidates = [
|
|
784
|
-
err?.response?.data?.code,
|
|
785
|
-
err?.code,
|
|
786
|
-
err?.status,
|
|
787
|
-
err?.statusCode,
|
|
788
|
-
err?.response?.data?.statusCode
|
|
789
|
-
];
|
|
790
|
-
let code = statusCandidates
|
|
791
|
-
.map(v => Number(v))
|
|
792
|
-
.find(v => Number.isFinite(v) && v >= 400) ?? 500;
|
|
793
|
-
const message = err?.response?.data?.errorMessage ??
|
|
794
|
-
err?.response?.data?.message ??
|
|
795
|
-
err?.message ??
|
|
796
|
-
`The request '${req.url}' resulted in a server error.`;
|
|
797
|
-
response.status(code);
|
|
798
|
-
const payload = { message };
|
|
799
|
-
if (this._formatResponse) {
|
|
800
|
-
return res.end(JSON.stringify(this._formatResponse(payload, code)));
|
|
801
|
-
}
|
|
802
|
-
return res.end(JSON.stringify(payload));
|
|
803
|
-
};
|
|
804
|
-
response.ok = (results) => {
|
|
805
|
-
return response.json(results == null ? {} : results);
|
|
806
|
-
};
|
|
807
|
-
response.created = (results) => {
|
|
808
|
-
response.status(201);
|
|
809
|
-
return response.json(results == null ? {} : results);
|
|
810
|
-
};
|
|
811
|
-
response.accepted = (results) => {
|
|
812
|
-
response.status(202);
|
|
813
|
-
return response.json(results == null ? {} : results);
|
|
814
|
-
};
|
|
815
|
-
response.noContent = () => {
|
|
816
|
-
response.status(204);
|
|
817
|
-
return res.end();
|
|
818
|
-
};
|
|
819
|
-
response.badRequest = (message) => {
|
|
820
|
-
if (res.writableEnded)
|
|
821
|
-
return;
|
|
822
|
-
response.status(400);
|
|
823
|
-
message = message ?? `The request '${req.url}' resulted in a bad request. Please review the data and try again.`;
|
|
824
|
-
if (this._formatResponse != null) {
|
|
825
|
-
return res.end(JSON.stringify(this._formatResponse({ message }, 400), null, 2));
|
|
826
|
-
}
|
|
827
|
-
return res.end(JSON.stringify({
|
|
828
|
-
message: message
|
|
829
|
-
}, null, 2));
|
|
830
|
-
};
|
|
831
|
-
response.unauthorized = (message) => {
|
|
832
|
-
response.status(401);
|
|
833
|
-
message = message ?? `The request '${req.url}' is unauthorized. Please verify.`;
|
|
834
|
-
if (this._formatResponse != null) {
|
|
835
|
-
return res.end(JSON.stringify(this._formatResponse({ message }, 401), null, 2));
|
|
836
|
-
}
|
|
837
|
-
return res.end(JSON.stringify({
|
|
838
|
-
message
|
|
839
|
-
}, null, 2));
|
|
840
|
-
};
|
|
841
|
-
response.paymentRequired = (message) => {
|
|
842
|
-
response.status(402);
|
|
843
|
-
message = message ?? `The request '${req.url}' requires payment. Please proceed with payment.`;
|
|
844
|
-
if (this._formatResponse != null) {
|
|
845
|
-
return res.end(JSON.stringify(this._formatResponse({ message }, 402), null, 2));
|
|
846
|
-
}
|
|
847
|
-
return res.end(JSON.stringify({
|
|
848
|
-
message
|
|
849
|
-
}, null, 2));
|
|
850
|
-
};
|
|
851
|
-
response.forbidden = (message) => {
|
|
852
|
-
response.status(403);
|
|
853
|
-
message = message ?? `The request '${req.url}' is forbidden. Please check the permissions or access rights.`;
|
|
854
|
-
if (this._formatResponse != null) {
|
|
855
|
-
return res.end(JSON.stringify(this._formatResponse({ message }, 403), null, 2));
|
|
856
|
-
}
|
|
857
|
-
return res.end(JSON.stringify({
|
|
858
|
-
message
|
|
859
|
-
}, null, 2));
|
|
860
|
-
};
|
|
861
|
-
response.notFound = (message) => {
|
|
862
|
-
response.status(404);
|
|
863
|
-
message = message ?? `The request '${req.url}' was not found. Please re-check the your url again.`;
|
|
864
|
-
if (this._formatResponse != null) {
|
|
865
|
-
return res.end(JSON.stringify(this._formatResponse({ message }, 404), null, 2));
|
|
866
|
-
}
|
|
867
|
-
return res.end(JSON.stringify({
|
|
868
|
-
message
|
|
869
|
-
}, null, 2));
|
|
870
|
-
};
|
|
871
|
-
response.unprocessable = (message) => {
|
|
872
|
-
response.status(422);
|
|
873
|
-
message = message ?? `The request to '${req.url}' failed validation.`;
|
|
874
|
-
if (this._formatResponse != null) {
|
|
875
|
-
return res.end(JSON.stringify(this._formatResponse({ message }, 422), null, 2));
|
|
876
|
-
}
|
|
877
|
-
return res.end(JSON.stringify({
|
|
878
|
-
message
|
|
879
|
-
}, null, 2));
|
|
880
|
-
};
|
|
881
|
-
response.tooManyRequests = (message) => {
|
|
882
|
-
response.status(429);
|
|
883
|
-
message = message ?? `The request '${req.url}' is too many request. Please wait and try agian.`;
|
|
884
|
-
if (this._formatResponse != null) {
|
|
885
|
-
return res.end(JSON.stringify(this._formatResponse({ message }, 429), null, 2));
|
|
886
|
-
}
|
|
887
|
-
return res.end(JSON.stringify({
|
|
888
|
-
message
|
|
889
|
-
}, null, 2));
|
|
890
|
-
};
|
|
891
|
-
response.serverError = (message) => {
|
|
892
|
-
response.status(500);
|
|
893
|
-
message = message ?? `The request '${req.url}' resulted in a server error. Please investigate.`;
|
|
894
|
-
if (this._formatResponse != null) {
|
|
895
|
-
return res.end(JSON.stringify(this._formatResponse({ message }, 500), null, 2));
|
|
896
|
-
}
|
|
897
|
-
return res.end(JSON.stringify({
|
|
898
|
-
message
|
|
899
|
-
}, null, 2));
|
|
900
|
-
};
|
|
901
|
-
response.status = (code) => {
|
|
902
|
-
res.writeHead(code, { 'Content-Type': 'application/json' });
|
|
903
|
-
return res;
|
|
904
|
-
};
|
|
905
|
-
response.setCookies = (cookies) => {
|
|
906
|
-
for (const [key, v] of Object.entries(cookies)) {
|
|
907
|
-
if (typeof v === 'string') {
|
|
908
|
-
res.setHeader('Set-Cookie', `${key}=${v}`);
|
|
909
|
-
continue;
|
|
910
|
-
}
|
|
911
|
-
if (v.value === '' || v.value == null)
|
|
912
|
-
continue;
|
|
913
|
-
let str = `${key}=${v.value}`;
|
|
914
|
-
if (v.sameSite != null) {
|
|
915
|
-
str += ` ;SameSite=${v.sameSite}`;
|
|
916
|
-
}
|
|
917
|
-
if (v.domain != null) {
|
|
918
|
-
str += ` ;Domain=${v.domain}`;
|
|
919
|
-
}
|
|
920
|
-
if (v.httpOnly != null) {
|
|
921
|
-
str += ` ;HttpOnly`;
|
|
922
|
-
}
|
|
923
|
-
if (v.secure != null) {
|
|
924
|
-
str += ` ;Secure`;
|
|
925
|
-
}
|
|
926
|
-
if (v.expires != null) {
|
|
927
|
-
str += ` ;Expires=${v.expires.toUTCString()}`;
|
|
928
|
-
}
|
|
929
|
-
res.setHeader('Set-Cookie', str);
|
|
930
|
-
}
|
|
931
|
-
};
|
|
932
|
-
return response;
|
|
933
|
-
}
|
|
934
739
|
_wrapHandlers(...handlers) {
|
|
935
|
-
return (req, res,
|
|
936
|
-
const
|
|
740
|
+
return (req, res, ps) => {
|
|
741
|
+
const dispatch = (index = 0) => {
|
|
742
|
+
const handler = handlers[index];
|
|
743
|
+
if (!handler)
|
|
744
|
+
return;
|
|
745
|
+
const ctx = this._createContext({ req, res, ps });
|
|
937
746
|
try {
|
|
938
|
-
const
|
|
939
|
-
const
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
const files = request.files;
|
|
943
|
-
const cookies = request.cookies;
|
|
944
|
-
const headers = request.headers;
|
|
945
|
-
const url = new url_1.URL(req.url, "http://localhost");
|
|
946
|
-
const query = Object.fromEntries(url.searchParams);
|
|
947
|
-
const RecordOrEmptyRecord = (data) => {
|
|
948
|
-
if (data == null)
|
|
949
|
-
return {};
|
|
950
|
-
return Object.keys(data).length ? data : {};
|
|
951
|
-
};
|
|
952
|
-
const ctx = {
|
|
953
|
-
req: request,
|
|
954
|
-
res: response,
|
|
955
|
-
headers: RecordOrEmptyRecord(headers),
|
|
956
|
-
params: RecordOrEmptyRecord(params),
|
|
957
|
-
query: RecordOrEmptyRecord(query),
|
|
958
|
-
body: RecordOrEmptyRecord(body),
|
|
959
|
-
files: RecordOrEmptyRecord(files),
|
|
960
|
-
cookies: RecordOrEmptyRecord(cookies)
|
|
961
|
-
};
|
|
962
|
-
if (index === handlers.length - 1) {
|
|
963
|
-
return this._wrapResponse(handlers[index]
|
|
964
|
-
.bind(handlers[index]))(ctx, this._nextFunction(ctx));
|
|
747
|
+
const next = () => dispatch(index + 1);
|
|
748
|
+
const isLast = index === handlers.length - 1;
|
|
749
|
+
if (isLast) {
|
|
750
|
+
return this._wrapResponse(handler)(ctx, this._nextError(ctx));
|
|
965
751
|
}
|
|
966
|
-
return
|
|
967
|
-
return nextHandler(index + 1);
|
|
968
|
-
});
|
|
752
|
+
return handler(ctx, next);
|
|
969
753
|
}
|
|
970
754
|
catch (err) {
|
|
971
|
-
|
|
972
|
-
req,
|
|
973
|
-
res: this._customizeResponse(req, res),
|
|
974
|
-
params: Object.keys(params).length ? params : {},
|
|
975
|
-
headers: {},
|
|
976
|
-
query: {},
|
|
977
|
-
body: {},
|
|
978
|
-
files: {},
|
|
979
|
-
cookies: {}
|
|
980
|
-
};
|
|
981
|
-
return this._nextFunction(ctx)(err);
|
|
755
|
+
return this._nextError(ctx)(err);
|
|
982
756
|
}
|
|
983
757
|
};
|
|
984
|
-
|
|
985
|
-
return;
|
|
986
|
-
return nextHandler();
|
|
758
|
+
return dispatch();
|
|
987
759
|
};
|
|
988
760
|
}
|
|
989
761
|
_wrapResponse(handler) {
|
|
990
762
|
return (ctx, next) => {
|
|
991
763
|
Promise.resolve(handler(ctx, next))
|
|
992
764
|
.then(result => {
|
|
993
|
-
if (ctx.res.writableEnded)
|
|
765
|
+
if (ctx.res.writableEnded) {
|
|
994
766
|
return;
|
|
767
|
+
}
|
|
995
768
|
if (result instanceof http_1.ServerResponse) {
|
|
996
|
-
if (result?.end) {
|
|
997
|
-
result.end();
|
|
998
|
-
}
|
|
999
769
|
return;
|
|
1000
770
|
}
|
|
1001
|
-
if (result
|
|
1002
|
-
if (!ctx.res.headersSent) {
|
|
1003
|
-
ctx.res.writeHead(204, { 'Content-Type': 'text/plain' });
|
|
1004
|
-
}
|
|
1005
|
-
ctx.res.end();
|
|
771
|
+
if (result instanceof stream_1.Stream) {
|
|
1006
772
|
return;
|
|
1007
773
|
}
|
|
1008
|
-
if (
|
|
1009
|
-
|
|
1010
|
-
ctx.res.writeHead(200, { 'Content-Type': 'text/plain' });
|
|
1011
|
-
}
|
|
1012
|
-
ctx.res.end(result ?? '');
|
|
774
|
+
if (result == null) {
|
|
775
|
+
ctx.res.noContent();
|
|
1013
776
|
return;
|
|
1014
777
|
}
|
|
1015
|
-
if (
|
|
1016
|
-
|
|
1017
|
-
if (typeof formattedResult === 'string') {
|
|
1018
|
-
if (!ctx.res.headersSent) {
|
|
1019
|
-
ctx.res.writeHead(200, { 'Content-Type': 'text/plain' });
|
|
1020
|
-
}
|
|
1021
|
-
ctx.res.end(formattedResult);
|
|
1022
|
-
return;
|
|
1023
|
-
}
|
|
1024
|
-
if (!ctx.res.headersSent) {
|
|
1025
|
-
ctx.res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
1026
|
-
}
|
|
1027
|
-
ctx.res.end(JSON.stringify(formattedResult));
|
|
778
|
+
if (typeof result === 'string') {
|
|
779
|
+
ctx.res.send(result);
|
|
1028
780
|
return;
|
|
1029
781
|
}
|
|
1030
|
-
|
|
1031
|
-
ctx.res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
1032
|
-
}
|
|
1033
|
-
ctx.res.end(JSON.stringify(result));
|
|
782
|
+
ctx.res.json(result);
|
|
1034
783
|
return;
|
|
1035
784
|
})
|
|
1036
|
-
.catch(err =>
|
|
1037
|
-
return this._nextFunction(ctx)(err);
|
|
1038
|
-
});
|
|
785
|
+
.catch(err => next(err));
|
|
1039
786
|
};
|
|
1040
787
|
}
|
|
1041
|
-
|
|
788
|
+
_nextError(ctx) {
|
|
1042
789
|
const NEXT_MESSAGE = "The 'next' function does not have any subsequent function.";
|
|
1043
790
|
return (err) => {
|
|
1044
|
-
|
|
1045
|
-
if (this._errorHandler != null) {
|
|
1046
|
-
const callback = this._errorHandler(err, ctx);
|
|
1047
|
-
if (callback == null || !(callback instanceof http_1.ServerResponse)) {
|
|
1048
|
-
ctx.res.writeHead(500, { 'Content-Type': 'application/json' });
|
|
1049
|
-
return ctx.res.end(JSON.stringify({
|
|
1050
|
-
message: err?.message
|
|
1051
|
-
}, null, 2));
|
|
1052
|
-
}
|
|
1053
|
-
return callback;
|
|
1054
|
-
}
|
|
1055
|
-
ctx.res.writeHead(500, { 'Content-Type': 'application/json' });
|
|
1056
|
-
if (this._formatResponse != null) {
|
|
1057
|
-
return ctx.res.end(JSON.stringify(this._formatResponse({
|
|
1058
|
-
message: err?.message,
|
|
1059
|
-
}, ctx.res.statusCode), null, 2));
|
|
1060
|
-
}
|
|
1061
|
-
return ctx.res.end(JSON.stringify({
|
|
1062
|
-
message: err?.message
|
|
1063
|
-
}, null, 2));
|
|
1064
|
-
}
|
|
791
|
+
const errorMessage = err?.message || NEXT_MESSAGE;
|
|
1065
792
|
if (this._errorHandler != null) {
|
|
1066
|
-
return this._errorHandler(new Error(
|
|
793
|
+
return this._errorHandler(new Error(errorMessage), ctx);
|
|
794
|
+
}
|
|
795
|
+
if (!ctx.res.headersSent) {
|
|
796
|
+
ctx.res.writeHead(500, const_1.HEADER_CONTENT_TYPES['json']);
|
|
1067
797
|
}
|
|
1068
|
-
ctx.res.writeHead(500, { 'Content-Type': 'application/json' });
|
|
1069
798
|
if (this._formatResponse != null) {
|
|
1070
|
-
|
|
1071
|
-
message:
|
|
1072
|
-
}, ctx.res.statusCode)
|
|
799
|
+
ctx.res.end(JSON.stringify(this._formatResponse({
|
|
800
|
+
message: errorMessage
|
|
801
|
+
}, ctx.res.statusCode)));
|
|
802
|
+
return;
|
|
1073
803
|
}
|
|
1074
|
-
|
|
1075
|
-
message:
|
|
1076
|
-
}
|
|
804
|
+
ctx.res.end(JSON.stringify({
|
|
805
|
+
message: errorMessage
|
|
806
|
+
}));
|
|
807
|
+
return;
|
|
1077
808
|
};
|
|
1078
809
|
}
|
|
810
|
+
_clusterMode({ server, port, hostname, callback }) {
|
|
811
|
+
if (cluster_1.default.isPrimary) {
|
|
812
|
+
const numCPUs = os_1.default.cpus().length;
|
|
813
|
+
const maxWorkers = typeof this._cluster === 'boolean' || this._cluster == null
|
|
814
|
+
? numCPUs
|
|
815
|
+
: this._cluster;
|
|
816
|
+
for (let i = 0; i < maxWorkers; i++) {
|
|
817
|
+
cluster_1.default.fork();
|
|
818
|
+
}
|
|
819
|
+
cluster_1.default.on('exit', () => {
|
|
820
|
+
cluster_1.default.fork();
|
|
821
|
+
});
|
|
822
|
+
}
|
|
823
|
+
if (cluster_1.default.isWorker) {
|
|
824
|
+
if (this._adapter.kind === 'uWS') {
|
|
825
|
+
const handler = () => {
|
|
826
|
+
this._onListeners.forEach(listener => listener());
|
|
827
|
+
if (this._swagger.use) {
|
|
828
|
+
this._swaggerHandler();
|
|
829
|
+
}
|
|
830
|
+
callback?.({ server, port });
|
|
831
|
+
};
|
|
832
|
+
if (hostname) {
|
|
833
|
+
server.listen(port, hostname, handler);
|
|
834
|
+
return server;
|
|
835
|
+
}
|
|
836
|
+
server.listen(port, handler);
|
|
837
|
+
return server;
|
|
838
|
+
}
|
|
839
|
+
const args = hostname
|
|
840
|
+
? [port, hostname, () => callback?.({ server, port: port })]
|
|
841
|
+
: [port, () => callback?.({ server, port: port })];
|
|
842
|
+
server.listen(...args);
|
|
843
|
+
server.on('listening', () => {
|
|
844
|
+
this._onListeners.forEach(listener => listener());
|
|
845
|
+
if (this._swagger.use) {
|
|
846
|
+
this._swaggerHandler();
|
|
847
|
+
}
|
|
848
|
+
});
|
|
849
|
+
server.on('error', (_) => {
|
|
850
|
+
port = Math.floor(Math.random() * 8999) + 1000;
|
|
851
|
+
server.listen(port);
|
|
852
|
+
});
|
|
853
|
+
}
|
|
854
|
+
return;
|
|
855
|
+
}
|
|
1079
856
|
async _createServer() {
|
|
1080
857
|
await this._registerMiddlewares();
|
|
1081
858
|
await this._registerControllers();
|
|
1082
859
|
const lookup = this._router.lookup.bind(this._router);
|
|
1083
860
|
const cors = this._cors;
|
|
1084
|
-
const
|
|
1085
|
-
|
|
1086
|
-
|
|
861
|
+
const adapter = this._adapter;
|
|
862
|
+
if (adapter.kind === 'uWS') {
|
|
863
|
+
const server = adapter.server.App();
|
|
864
|
+
server.any('/*', (uwsRes, uwsReq) => {
|
|
865
|
+
const { req, res } = (0, uWS_1.uWSAdaptRequestResponse)(uwsReq, uwsRes);
|
|
866
|
+
if (cors)
|
|
867
|
+
cors(req, res);
|
|
1087
868
|
return lookup(req, res);
|
|
869
|
+
});
|
|
870
|
+
if (this._ws?.handler) {
|
|
871
|
+
server.ws('/*', {
|
|
872
|
+
open: (ws) => {
|
|
873
|
+
this._ws.handler?.connection?.(ws);
|
|
874
|
+
},
|
|
875
|
+
message: (ws, message) => {
|
|
876
|
+
this._ws.handler?.message?.(ws, Buffer.from(message));
|
|
877
|
+
},
|
|
878
|
+
close: (ws, code, message) => {
|
|
879
|
+
this._ws.handler?.close?.(ws, code, Buffer.from(message));
|
|
880
|
+
}
|
|
881
|
+
});
|
|
1088
882
|
}
|
|
1089
|
-
|
|
1090
|
-
|
|
883
|
+
return server;
|
|
884
|
+
}
|
|
885
|
+
if (adapter.kind === 'net') {
|
|
886
|
+
const server = net_1.default.createServer((socket) => {
|
|
887
|
+
(0, net_2.netAdaptRequestResponse)(socket, (req, res) => {
|
|
888
|
+
if (cors)
|
|
889
|
+
cors(req, res);
|
|
890
|
+
return lookup(req, res);
|
|
891
|
+
});
|
|
1091
892
|
});
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
893
|
+
if (this._ws?.handler) {
|
|
894
|
+
this._ws.server = new ws_1.default.Server({ server, ...this._ws.options });
|
|
895
|
+
this._ws.server.on('connection', (ws) => {
|
|
896
|
+
if (this._ws.handler?.connection) {
|
|
897
|
+
this._ws.handler.connection(ws);
|
|
898
|
+
}
|
|
899
|
+
ws.on('message', (data) => {
|
|
900
|
+
this._ws.handler?.message?.(ws, data);
|
|
901
|
+
});
|
|
902
|
+
ws.on('close', (code, reason) => {
|
|
903
|
+
if (this._ws.handler?.close) {
|
|
904
|
+
this._ws.handler?.close(ws, code, reason);
|
|
905
|
+
}
|
|
906
|
+
});
|
|
907
|
+
ws.on('error', (err) => {
|
|
908
|
+
if (this._ws.handler?.error) {
|
|
909
|
+
this._ws.handler.error(ws, err);
|
|
910
|
+
}
|
|
911
|
+
});
|
|
912
|
+
});
|
|
913
|
+
}
|
|
914
|
+
return server;
|
|
915
|
+
}
|
|
916
|
+
const server = http_1.default.createServer((req, res) => {
|
|
917
|
+
if (cors)
|
|
918
|
+
cors(req, res);
|
|
919
|
+
return lookup(req, res);
|
|
920
|
+
});
|
|
921
|
+
if (this._ws?.handler) {
|
|
922
|
+
this._ws.server = new ws_1.default.Server({ server, ...this._ws.options });
|
|
923
|
+
this._ws.server.on('connection', (ws) => {
|
|
924
|
+
if (this._ws.handler?.connection) {
|
|
925
|
+
this._ws.handler.connection(ws);
|
|
1097
926
|
}
|
|
1098
927
|
ws.on('message', (data) => {
|
|
1099
|
-
|
|
1100
|
-
this._ws.message(ws, data);
|
|
1101
|
-
}
|
|
928
|
+
this._ws.handler?.message?.(ws, data);
|
|
1102
929
|
});
|
|
1103
930
|
ws.on('close', (code, reason) => {
|
|
1104
|
-
if (this._ws?.close) {
|
|
1105
|
-
this._ws.close(ws, code, reason);
|
|
931
|
+
if (this._ws.handler?.close) {
|
|
932
|
+
this._ws.handler?.close(ws, code, reason);
|
|
1106
933
|
}
|
|
1107
934
|
});
|
|
1108
935
|
ws.on('error', (err) => {
|
|
1109
|
-
if (this._ws?.error) {
|
|
1110
|
-
this._ws.error(ws, err);
|
|
936
|
+
if (this._ws.handler?.error) {
|
|
937
|
+
this._ws.handler.error(ws, err);
|
|
1111
938
|
}
|
|
1112
939
|
});
|
|
1113
940
|
});
|
|
1114
941
|
}
|
|
1115
942
|
return server;
|
|
1116
943
|
}
|
|
944
|
+
_createContext({ req, res, ps }) {
|
|
945
|
+
const request = req;
|
|
946
|
+
const response = (0, response_1.Response)(req, res, {
|
|
947
|
+
formatResponse: this._formatResponse,
|
|
948
|
+
isUwebSocket: this._adapter.kind === 'uWS'
|
|
949
|
+
});
|
|
950
|
+
const headers = req.headers;
|
|
951
|
+
const params = ps;
|
|
952
|
+
const body = request.body;
|
|
953
|
+
const files = request.files;
|
|
954
|
+
const cookies = request.cookies;
|
|
955
|
+
const query = this._parser.queryString(req.url) || {};
|
|
956
|
+
const xff = headers['x-forwarded-for'];
|
|
957
|
+
const xrip = headers['x-real-ip'];
|
|
958
|
+
const cfip = headers['cf-connecting-ip'];
|
|
959
|
+
let ips = [];
|
|
960
|
+
if (cfip) {
|
|
961
|
+
ips = Array.isArray(cfip) ? cfip : [cfip];
|
|
962
|
+
}
|
|
963
|
+
else if (xff) {
|
|
964
|
+
ips = Array.isArray(xff) ? xff : [xff];
|
|
965
|
+
}
|
|
966
|
+
else if (xrip) {
|
|
967
|
+
ips = Array.isArray(xrip) ? xrip : [xrip];
|
|
968
|
+
}
|
|
969
|
+
else {
|
|
970
|
+
const addr = req.socket?.remoteAddress;
|
|
971
|
+
ips = addr ? [addr] : [];
|
|
972
|
+
}
|
|
973
|
+
const ip = (ips.length ? ips[0] : null);
|
|
974
|
+
request.params = params;
|
|
975
|
+
request.query = query;
|
|
976
|
+
request.ip = ip;
|
|
977
|
+
request.ips = ips;
|
|
978
|
+
return {
|
|
979
|
+
req: request,
|
|
980
|
+
res: response,
|
|
981
|
+
headers: headers || Object.create(null),
|
|
982
|
+
params: params || Object.create(null),
|
|
983
|
+
query,
|
|
984
|
+
body: body || Object.create(null),
|
|
985
|
+
files: files || Object.create(null),
|
|
986
|
+
cookies: cookies || Object.create(null),
|
|
987
|
+
ip,
|
|
988
|
+
ips
|
|
989
|
+
};
|
|
990
|
+
}
|
|
1117
991
|
_normalizePath(...paths) {
|
|
1118
992
|
const path = paths
|
|
1119
993
|
.join('/')
|
|
@@ -1141,10 +1015,10 @@ class Spear {
|
|
|
1141
1015
|
routes
|
|
1142
1016
|
});
|
|
1143
1017
|
this._router.get(staticUrl, staticSwaggerHandler);
|
|
1144
|
-
this._router.get(path, (
|
|
1145
|
-
res.writeHead(200,
|
|
1146
|
-
res.
|
|
1147
|
-
return
|
|
1018
|
+
this._router.get(path, (req, res) => {
|
|
1019
|
+
res.writeHead(200, const_1.HEADER_CONTENT_TYPES['html']);
|
|
1020
|
+
res.end(html);
|
|
1021
|
+
return;
|
|
1148
1022
|
});
|
|
1149
1023
|
return;
|
|
1150
1024
|
}
|