tspace-spear 1.2.3 → 1.2.5-beta.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.
- package/README.md +268 -19
- package/dist/lib/core/client/index.d.ts +23 -0
- package/dist/lib/core/client/index.js +45 -0
- package/dist/lib/core/client/index.js.map +1 -0
- package/dist/lib/core/compiler/generator.d.ts +18 -0
- package/dist/lib/core/compiler/generator.js +142 -0
- package/dist/lib/core/compiler/generator.js.map +1 -0
- package/dist/lib/core/compiler/index.d.ts +14 -0
- package/dist/lib/core/compiler/index.js +11 -0
- package/dist/lib/core/compiler/index.js.map +1 -0
- package/dist/lib/core/compiler/pre-routes.d.ts +3 -0
- package/dist/lib/core/compiler/pre-routes.js +5 -0
- package/dist/lib/core/compiler/pre-routes.js.map +1 -0
- package/dist/lib/core/compiler/types.d.ts +12 -0
- package/dist/lib/core/compiler/types.js +3 -0
- package/dist/lib/core/compiler/types.js.map +1 -0
- 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/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 +39 -37
- package/dist/lib/core/server/index.js +201 -501
- 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 +10 -11
- package/dist/lib/core/server/parser-factory.js +259 -437
- package/dist/lib/core/server/parser-factory.js.map +1 -1
- 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 -12
- package/dist/lib/core/server/router.js +2 -13
- 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 +150 -48
- 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 +4 -3
- package/dist/lib/index.js +4 -2
- package/dist/lib/index.js.map +1 -1
- package/package.json +20 -14
|
@@ -38,14 +38,21 @@ 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
47
|
const on_finished_1 = __importDefault(require("on-finished"));
|
|
47
48
|
const ws_1 = __importDefault(require("ws"));
|
|
49
|
+
const net_1 = __importDefault(require("net"));
|
|
48
50
|
const parser_factory_1 = require("./parser-factory");
|
|
51
|
+
const fast_router_1 = require("./fast-router");
|
|
52
|
+
const response_1 = require("./response");
|
|
53
|
+
const compiler_1 = require("../compiler");
|
|
54
|
+
const uWS_1 = require("./uWS");
|
|
55
|
+
const net_2 = require("./net");
|
|
49
56
|
/**
|
|
50
57
|
*
|
|
51
58
|
* The 'Spear' class is used to create a server and handle HTTP requests.
|
|
@@ -65,10 +72,10 @@ const parser_factory_1 = require("./parser-factory");
|
|
|
65
72
|
class Spear {
|
|
66
73
|
_controllers;
|
|
67
74
|
_middlewares;
|
|
68
|
-
|
|
69
|
-
_router = (0, find_my_way_1.default)();
|
|
75
|
+
_router = new fast_router_1.FastRouter();
|
|
70
76
|
_parser = new parser_factory_1.ParserFactory();
|
|
71
|
-
|
|
77
|
+
_globalPrefix = '';
|
|
78
|
+
_adapter = { kind: 'http', server: http_1.default };
|
|
72
79
|
_cluster;
|
|
73
80
|
_cors;
|
|
74
81
|
_swagger = {
|
|
@@ -76,7 +83,7 @@ class Spear {
|
|
|
76
83
|
path: '/api/docs',
|
|
77
84
|
servers: [
|
|
78
85
|
{
|
|
79
|
-
url: '
|
|
86
|
+
url: '/'
|
|
80
87
|
}
|
|
81
88
|
],
|
|
82
89
|
tags: [],
|
|
@@ -87,9 +94,11 @@ class Spear {
|
|
|
87
94
|
}
|
|
88
95
|
};
|
|
89
96
|
_swaggerSpecs = [];
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
97
|
+
_ws = {
|
|
98
|
+
handler: null,
|
|
99
|
+
server: null,
|
|
100
|
+
options: null
|
|
101
|
+
};
|
|
93
102
|
_errorHandler = null;
|
|
94
103
|
_globalMiddlewares = [];
|
|
95
104
|
_formatResponse = null;
|
|
@@ -102,16 +111,18 @@ class Spear {
|
|
|
102
111
|
ms: 1000 * 60 * 10
|
|
103
112
|
}
|
|
104
113
|
};
|
|
114
|
+
_generateRoutes;
|
|
105
115
|
constructor({ controllers, middlewares, globalPrefix, logger, cluster, adapter } = {}) {
|
|
116
|
+
this._controllers = controllers;
|
|
117
|
+
this._middlewares = middlewares;
|
|
106
118
|
if (logger)
|
|
107
119
|
this.useLogger();
|
|
108
120
|
if (cluster)
|
|
109
121
|
this.useCluster(cluster);
|
|
110
122
|
if (adapter)
|
|
111
123
|
this.useAdater(adapter);
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
this._globalPrefix = globalPrefix == null ? '' : globalPrefix;
|
|
124
|
+
if (globalPrefix)
|
|
125
|
+
this.useGlobalPrefix(globalPrefix);
|
|
115
126
|
}
|
|
116
127
|
/**
|
|
117
128
|
* The get 'instance' method is used to get the instance of Spear.
|
|
@@ -124,11 +135,15 @@ class Spear {
|
|
|
124
135
|
/**
|
|
125
136
|
* The get 'routers' method is used get the all routers.
|
|
126
137
|
*
|
|
127
|
-
* @returns {
|
|
138
|
+
* @returns {FastRouter}
|
|
128
139
|
*/
|
|
129
140
|
get routers() {
|
|
130
141
|
return this._router;
|
|
131
142
|
}
|
|
143
|
+
useGenerateRouteType(options) {
|
|
144
|
+
this._generateRoutes = options;
|
|
145
|
+
return this;
|
|
146
|
+
}
|
|
132
147
|
/**
|
|
133
148
|
* The 'ws' method is used to creates the WebSocket server.
|
|
134
149
|
*
|
|
@@ -137,8 +152,8 @@ class Spear {
|
|
|
137
152
|
* @returns {this}
|
|
138
153
|
*/
|
|
139
154
|
ws(handlers, options) {
|
|
140
|
-
this._ws = handlers();
|
|
141
|
-
this.
|
|
155
|
+
this._ws.handler = handlers();
|
|
156
|
+
this._ws.options = options ?? {};
|
|
142
157
|
return this;
|
|
143
158
|
}
|
|
144
159
|
/**
|
|
@@ -153,16 +168,38 @@ class Spear {
|
|
|
153
168
|
this._globalMiddlewares.push(middleware);
|
|
154
169
|
return this;
|
|
155
170
|
}
|
|
171
|
+
/**
|
|
172
|
+
* The 'useGlobalPrefix' method is used to sets a global prefix for all routes in the router.
|
|
173
|
+
*
|
|
174
|
+
* If `globalPrefix` is `null` or `undefined`, it will default to an empty string,
|
|
175
|
+
* meaning no prefix will be applied.
|
|
176
|
+
*
|
|
177
|
+
* @param {string | null} globalPrefix - The base path prefix to apply to all routes.
|
|
178
|
+
* @returns {this} Returns the current instance for method chaining.
|
|
179
|
+
*/
|
|
180
|
+
useGlobalPrefix(globalPrefix) {
|
|
181
|
+
this._globalPrefix = globalPrefix == null ? '' : globalPrefix;
|
|
182
|
+
return this;
|
|
183
|
+
}
|
|
156
184
|
/**
|
|
157
185
|
* The 'useAdater' method is used to switch between different server implementations,
|
|
158
186
|
* such as the native Node.js HTTP server or uWebSockets.js (uWS).
|
|
159
187
|
*
|
|
160
|
-
* @param {T.
|
|
188
|
+
* @param {T.AdapterServer} adapter - The adapter instance (e.g., HTTP or uWS).
|
|
161
189
|
* @returns {this} Returns the current instance for chaining
|
|
162
190
|
*/
|
|
163
191
|
useAdater(adapter) {
|
|
164
|
-
|
|
165
|
-
|
|
192
|
+
if (adapter === http_1.default) {
|
|
193
|
+
this._adapter = { kind: 'http', server: adapter };
|
|
194
|
+
}
|
|
195
|
+
else if (adapter === net_1.default) {
|
|
196
|
+
this._adapter = { kind: 'net', server: adapter };
|
|
197
|
+
}
|
|
198
|
+
else {
|
|
199
|
+
//@ts-ignore
|
|
200
|
+
this._adapter = { kind: 'uWS', server: adapter };
|
|
201
|
+
}
|
|
202
|
+
this._parser.useAdater(this._adapter);
|
|
166
203
|
return this;
|
|
167
204
|
}
|
|
168
205
|
/**
|
|
@@ -201,13 +238,13 @@ class Spear {
|
|
|
201
238
|
? `\x1b[32m${statusCode}\x1b[0m`
|
|
202
239
|
: `\x1b[31m${statusCode}\x1b[0m`;
|
|
203
240
|
};
|
|
204
|
-
if (exceptPath instanceof RegExp && exceptPath.test(
|
|
241
|
+
if (exceptPath instanceof RegExp && exceptPath.test(req.url))
|
|
205
242
|
return next();
|
|
206
|
-
if (Array.isArray(exceptPath) && exceptPath.some(v =>
|
|
243
|
+
if (Array.isArray(exceptPath) && exceptPath.some(v => req.url === v))
|
|
207
244
|
return next();
|
|
208
245
|
if (methods != null &&
|
|
209
246
|
methods.length &&
|
|
210
|
-
!methods.some(v => v.
|
|
247
|
+
!methods.some(v => v.toLowerCase() === req.method.toLowerCase())) {
|
|
211
248
|
return next();
|
|
212
249
|
}
|
|
213
250
|
const startTime = process.hrtime();
|
|
@@ -216,7 +253,7 @@ class Spear {
|
|
|
216
253
|
`[\x1b[1m\x1b[34mINFO\x1b[0m]`,
|
|
217
254
|
`\x1b[34m${new Date().toJSON()}\x1b[0m`,
|
|
218
255
|
`\x1b[33m${req.method}\x1b[0m`,
|
|
219
|
-
`${decodeURIComponent(
|
|
256
|
+
`${decodeURIComponent(req.url)}`,
|
|
220
257
|
`${statusCode(res)}`,
|
|
221
258
|
`${diffTime(startTime)}`,
|
|
222
259
|
].join(" "));
|
|
@@ -234,28 +271,25 @@ class Spear {
|
|
|
234
271
|
useBodyParser({ except } = {}) {
|
|
235
272
|
this._globalMiddlewares.push((ctx, next) => {
|
|
236
273
|
const { req, res } = ctx;
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
const isCanParserBody = contentType.includes('application/json') ||
|
|
240
|
-
contentType.includes('application/x-www-form-urlencoded');
|
|
241
|
-
if (except != null &&
|
|
242
|
-
Array.isArray(except) &&
|
|
243
|
-
except.some(v => v.toLocaleLowerCase() === (req.method)?.toLocaleLowerCase())) {
|
|
274
|
+
if (Array.isArray(except) &&
|
|
275
|
+
except.some(v => v.toLowerCase() === (req.method).toLowerCase())) {
|
|
244
276
|
return next();
|
|
245
277
|
}
|
|
246
|
-
|
|
278
|
+
const contentType = req?.headers['content-type'] ?? null;
|
|
279
|
+
if (contentType == null)
|
|
247
280
|
return next();
|
|
248
|
-
|
|
281
|
+
const isFileUpload = contentType && contentType.startsWith('multipart/form-data');
|
|
282
|
+
if (isFileUpload)
|
|
249
283
|
return next();
|
|
250
284
|
if (req?.body != null)
|
|
251
285
|
return next();
|
|
252
286
|
Promise.resolve(this._parser.body(req, res))
|
|
253
|
-
.then(
|
|
254
|
-
req.body =
|
|
287
|
+
.then(body => {
|
|
288
|
+
req.body = body;
|
|
255
289
|
return next();
|
|
256
290
|
})
|
|
257
291
|
.catch(err => {
|
|
258
|
-
return this.
|
|
292
|
+
return this._nextError(ctx)(err);
|
|
259
293
|
});
|
|
260
294
|
});
|
|
261
295
|
return this;
|
|
@@ -264,11 +298,11 @@ class Spear {
|
|
|
264
298
|
* The 'useFileUpload' method is a middleware used to handler file uploads. It adds a file upload of incoming HTTP requests.
|
|
265
299
|
*
|
|
266
300
|
* @param {?Object}
|
|
267
|
-
* @property {?number} limits
|
|
301
|
+
* @property {?number} limits // bytes. default Infinity
|
|
268
302
|
* @property {?string} tempFileDir
|
|
269
303
|
* @property {?Object} removeTempFile
|
|
270
304
|
* @property {boolean} removeTempFile.remove
|
|
271
|
-
* @property {number}
|
|
305
|
+
* @property {number} removeTempFile.ms
|
|
272
306
|
* @returns
|
|
273
307
|
*/
|
|
274
308
|
useFileUpload({ limit, tempFileDir, removeTempFile } = {}) {
|
|
@@ -300,7 +334,7 @@ class Spear {
|
|
|
300
334
|
return next();
|
|
301
335
|
})
|
|
302
336
|
.catch(err => {
|
|
303
|
-
return this.
|
|
337
|
+
return this._nextError(ctx)(err);
|
|
304
338
|
});
|
|
305
339
|
});
|
|
306
340
|
return this;
|
|
@@ -363,6 +397,9 @@ class Spear {
|
|
|
363
397
|
callback = hostname;
|
|
364
398
|
}
|
|
365
399
|
const server = await this._createServer();
|
|
400
|
+
if (this._generateRoutes) {
|
|
401
|
+
await new compiler_1.Compiler().generateRoutes(this._generateRoutes);
|
|
402
|
+
}
|
|
366
403
|
if (this._cluster != null &&
|
|
367
404
|
this._cluster || typeof this._cluster === 'number') {
|
|
368
405
|
this._clusterMode({
|
|
@@ -373,7 +410,7 @@ class Spear {
|
|
|
373
410
|
});
|
|
374
411
|
return server;
|
|
375
412
|
}
|
|
376
|
-
if (
|
|
413
|
+
if (this._adapter.kind === 'uWS') {
|
|
377
414
|
const handler = () => {
|
|
378
415
|
this._onListeners.forEach(listener => listener());
|
|
379
416
|
if (this._swagger.use) {
|
|
@@ -469,21 +506,10 @@ class Spear {
|
|
|
469
506
|
*/
|
|
470
507
|
notfound(fn) {
|
|
471
508
|
const handler = ({ req, res }) => {
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
res: this._customizeResponse(req, res),
|
|
475
|
-
headers: {},
|
|
476
|
-
query: {},
|
|
477
|
-
files: {},
|
|
478
|
-
body: {},
|
|
479
|
-
params: {},
|
|
480
|
-
cookies: {},
|
|
481
|
-
ip: null
|
|
482
|
-
});
|
|
509
|
+
const ctx = this._createContext({ req, res, ps: {} });
|
|
510
|
+
return fn(ctx);
|
|
483
511
|
};
|
|
484
|
-
this.
|
|
485
|
-
return this.all('*', ...this._globalMiddlewares, handler);
|
|
486
|
-
});
|
|
512
|
+
this.all('*', handler);
|
|
487
513
|
return this;
|
|
488
514
|
}
|
|
489
515
|
/**
|
|
@@ -592,7 +618,7 @@ class Spear {
|
|
|
592
618
|
return this;
|
|
593
619
|
}
|
|
594
620
|
/**
|
|
595
|
-
* The '
|
|
621
|
+
* The 'all' method is used to add the request handler to the router for 'GET' 'POST' 'PUT' 'PATCH' 'DELETE' 'HEAD' 'OPTIONS' methods.
|
|
596
622
|
*
|
|
597
623
|
* @param {string} path
|
|
598
624
|
* @callback {...Function[]} handlers of the middlewares
|
|
@@ -600,21 +626,6 @@ class Spear {
|
|
|
600
626
|
* @property {function} next - go to next function
|
|
601
627
|
* @returns {this}
|
|
602
628
|
*/
|
|
603
|
-
any(path, ...handlers) {
|
|
604
|
-
this._onListeners.push(() => {
|
|
605
|
-
return this._router.all(this._normalizePath(this._globalPrefix, path), this._wrapHandlers(...this._globalMiddlewares, ...handlers));
|
|
606
|
-
});
|
|
607
|
-
return this;
|
|
608
|
-
}
|
|
609
|
-
/**
|
|
610
|
-
* The 'all' method is used to add the request handler to the router for 'GET' 'POST' 'PUT' 'PATCH' 'DELETE' 'HEAD' 'OPTIONS' methods.
|
|
611
|
-
*
|
|
612
|
-
* @param {string} path
|
|
613
|
-
* @callback {...Function[]} handlers of the middlewares
|
|
614
|
-
* @property {object} ctx - context { req , res , query , params , cookies , files , body}
|
|
615
|
-
* @property {function} next - go to next function
|
|
616
|
-
* @returns {this}
|
|
617
|
-
*/
|
|
618
629
|
all(path, ...handlers) {
|
|
619
630
|
this._onListeners.push(() => {
|
|
620
631
|
return this._router.all(this._normalizePath(this._globalPrefix, path), this._wrapHandlers(...this._globalMiddlewares, ...handlers));
|
|
@@ -734,239 +745,23 @@ class Spear {
|
|
|
734
745
|
}
|
|
735
746
|
return;
|
|
736
747
|
}
|
|
737
|
-
_customizeResponse(req, res) {
|
|
738
|
-
const response = res;
|
|
739
|
-
response.json = (results) => {
|
|
740
|
-
if (res.writableEnded)
|
|
741
|
-
return;
|
|
742
|
-
if (typeof results === 'string') {
|
|
743
|
-
if (!res.headersSent) {
|
|
744
|
-
res.writeHead(200, { 'Content-Type': 'text/plain' });
|
|
745
|
-
}
|
|
746
|
-
return res.end(results);
|
|
747
|
-
}
|
|
748
|
-
if (!res.headersSent) {
|
|
749
|
-
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
750
|
-
}
|
|
751
|
-
if (results == null) {
|
|
752
|
-
if (this._formatResponse != null) {
|
|
753
|
-
return res.end(JSON.stringify(this._formatResponse(null, res.statusCode)));
|
|
754
|
-
}
|
|
755
|
-
return res.end();
|
|
756
|
-
}
|
|
757
|
-
if (this._formatResponse != null) {
|
|
758
|
-
return res.end(JSON.stringify(this._formatResponse({
|
|
759
|
-
...results
|
|
760
|
-
}, res.statusCode)));
|
|
761
|
-
}
|
|
762
|
-
return res.end(JSON.stringify({
|
|
763
|
-
...results,
|
|
764
|
-
}));
|
|
765
|
-
};
|
|
766
|
-
response.send = (results) => {
|
|
767
|
-
if (res.writableEnded)
|
|
768
|
-
return;
|
|
769
|
-
res.writeHead(res.statusCode, { 'Content-Type': 'text/plain' });
|
|
770
|
-
return res.end(results);
|
|
771
|
-
};
|
|
772
|
-
response.html = (results) => {
|
|
773
|
-
if (res.writableEnded)
|
|
774
|
-
return;
|
|
775
|
-
res.writeHead(res.statusCode, { 'Content-Type': 'text/html' });
|
|
776
|
-
return res.end(results);
|
|
777
|
-
};
|
|
778
|
-
response.error = (err) => {
|
|
779
|
-
const statusCandidates = [
|
|
780
|
-
err?.response?.data?.code,
|
|
781
|
-
err?.code,
|
|
782
|
-
err?.status,
|
|
783
|
-
err?.statusCode,
|
|
784
|
-
err?.response?.data?.statusCode
|
|
785
|
-
];
|
|
786
|
-
let code = statusCandidates
|
|
787
|
-
.map(v => Number(v))
|
|
788
|
-
.find(v => Number.isFinite(v) && v >= 400) ?? 500;
|
|
789
|
-
const message = err?.response?.data?.errorMessage ??
|
|
790
|
-
err?.response?.data?.message ??
|
|
791
|
-
err?.message ??
|
|
792
|
-
`The request '${req.url}' resulted in a server error.`;
|
|
793
|
-
response.status(code);
|
|
794
|
-
const payload = { message };
|
|
795
|
-
if (this._formatResponse) {
|
|
796
|
-
return res.end(JSON.stringify(this._formatResponse(payload, code)));
|
|
797
|
-
}
|
|
798
|
-
return res.end(JSON.stringify(payload));
|
|
799
|
-
};
|
|
800
|
-
response.ok = (results) => {
|
|
801
|
-
return response.json(results == null ? {} : results);
|
|
802
|
-
};
|
|
803
|
-
response.created = (results) => {
|
|
804
|
-
response.status(201);
|
|
805
|
-
return response.json(results == null ? {} : results);
|
|
806
|
-
};
|
|
807
|
-
response.accepted = (results) => {
|
|
808
|
-
response.status(202);
|
|
809
|
-
return response.json(results == null ? {} : results);
|
|
810
|
-
};
|
|
811
|
-
response.noContent = () => {
|
|
812
|
-
response.status(204);
|
|
813
|
-
return res.end();
|
|
814
|
-
};
|
|
815
|
-
response.badRequest = (message) => {
|
|
816
|
-
if (res.writableEnded)
|
|
817
|
-
return;
|
|
818
|
-
response.status(400);
|
|
819
|
-
message = message ?? `The request '${req.url}' resulted in a bad request. Please review the data and try again.`;
|
|
820
|
-
if (this._formatResponse != null) {
|
|
821
|
-
return res.end(JSON.stringify(this._formatResponse({ message }, 400)));
|
|
822
|
-
}
|
|
823
|
-
return res.end(JSON.stringify({
|
|
824
|
-
message: message
|
|
825
|
-
}));
|
|
826
|
-
};
|
|
827
|
-
response.unauthorized = (message) => {
|
|
828
|
-
response.status(401);
|
|
829
|
-
message = message ?? `The request '${req.url}' is unauthorized. Please verify.`;
|
|
830
|
-
if (this._formatResponse != null) {
|
|
831
|
-
return res.end(JSON.stringify(this._formatResponse({ message }, 401)));
|
|
832
|
-
}
|
|
833
|
-
return res.end(JSON.stringify({
|
|
834
|
-
message
|
|
835
|
-
}));
|
|
836
|
-
};
|
|
837
|
-
response.paymentRequired = (message) => {
|
|
838
|
-
response.status(402);
|
|
839
|
-
message = message ?? `The request '${req.url}' requires payment. Please proceed with payment.`;
|
|
840
|
-
if (this._formatResponse != null) {
|
|
841
|
-
return res.end(JSON.stringify(this._formatResponse({ message }, 402)));
|
|
842
|
-
}
|
|
843
|
-
return res.end(JSON.stringify({
|
|
844
|
-
message
|
|
845
|
-
}));
|
|
846
|
-
};
|
|
847
|
-
response.forbidden = (message) => {
|
|
848
|
-
response.status(403);
|
|
849
|
-
message = message ?? `The request '${req.url}' is forbidden. Please check the permissions or access rights.`;
|
|
850
|
-
if (this._formatResponse != null) {
|
|
851
|
-
return res.end(JSON.stringify(this._formatResponse({ message }, 403)));
|
|
852
|
-
}
|
|
853
|
-
return res.end(JSON.stringify({
|
|
854
|
-
message
|
|
855
|
-
}));
|
|
856
|
-
};
|
|
857
|
-
response.notFound = (message) => {
|
|
858
|
-
response.status(404);
|
|
859
|
-
message = message ?? `The request '${req.url}' was not found. Please re-check the your url again.`;
|
|
860
|
-
if (this._formatResponse != null) {
|
|
861
|
-
return res.end(JSON.stringify(this._formatResponse({ message }, 404)));
|
|
862
|
-
}
|
|
863
|
-
return res.end(JSON.stringify({
|
|
864
|
-
message
|
|
865
|
-
}));
|
|
866
|
-
};
|
|
867
|
-
response.unprocessable = (message) => {
|
|
868
|
-
response.status(422);
|
|
869
|
-
message = message ?? `The request to '${req.url}' failed validation.`;
|
|
870
|
-
if (this._formatResponse != null) {
|
|
871
|
-
return res.end(JSON.stringify(this._formatResponse({ message }, 422)));
|
|
872
|
-
}
|
|
873
|
-
return res.end(JSON.stringify({
|
|
874
|
-
message
|
|
875
|
-
}));
|
|
876
|
-
};
|
|
877
|
-
response.tooManyRequests = (message) => {
|
|
878
|
-
response.status(429);
|
|
879
|
-
message = message ?? `The request '${req.url}' is too many request. Please wait and try agian.`;
|
|
880
|
-
if (this._formatResponse != null) {
|
|
881
|
-
return res.end(JSON.stringify(this._formatResponse({ message }, 429)));
|
|
882
|
-
}
|
|
883
|
-
return res.end(JSON.stringify({
|
|
884
|
-
message
|
|
885
|
-
}));
|
|
886
|
-
};
|
|
887
|
-
response.serverError = (message) => {
|
|
888
|
-
response.status(500);
|
|
889
|
-
message = message ?? `The request '${req.url}' resulted in a server error. Please investigate.`;
|
|
890
|
-
if (this._formatResponse != null) {
|
|
891
|
-
return res.end(JSON.stringify(this._formatResponse({ message }, 500)));
|
|
892
|
-
}
|
|
893
|
-
return res.end(JSON.stringify({
|
|
894
|
-
message
|
|
895
|
-
}));
|
|
896
|
-
};
|
|
897
|
-
response.status = (code) => {
|
|
898
|
-
res.writeHead(code, { 'Content-Type': 'application/json' });
|
|
899
|
-
return res;
|
|
900
|
-
};
|
|
901
|
-
response.setCookies = (cookies) => {
|
|
902
|
-
for (const [key, v] of Object.entries(cookies)) {
|
|
903
|
-
if (typeof v === 'string') {
|
|
904
|
-
res.setHeader('Set-Cookie', `${key}=${v}`);
|
|
905
|
-
continue;
|
|
906
|
-
}
|
|
907
|
-
if (v.value === '' || v.value == null)
|
|
908
|
-
continue;
|
|
909
|
-
let str = `${key}=${v.value}`;
|
|
910
|
-
if (v.sameSite != null) {
|
|
911
|
-
str += ` ;SameSite=${v.sameSite}`;
|
|
912
|
-
}
|
|
913
|
-
if (v.domain != null) {
|
|
914
|
-
str += ` ;Domain=${v.domain}`;
|
|
915
|
-
}
|
|
916
|
-
if (v.httpOnly != null) {
|
|
917
|
-
str += ` ;HttpOnly`;
|
|
918
|
-
}
|
|
919
|
-
if (v.secure != null) {
|
|
920
|
-
str += ` ;Secure`;
|
|
921
|
-
}
|
|
922
|
-
if (v.expires != null) {
|
|
923
|
-
str += ` ;Expires=${v.expires.toUTCString()}`;
|
|
924
|
-
}
|
|
925
|
-
res.setHeader('Set-Cookie', str);
|
|
926
|
-
}
|
|
927
|
-
};
|
|
928
|
-
return response;
|
|
929
|
-
}
|
|
930
748
|
_wrapHandlers(...handlers) {
|
|
931
749
|
return (req, res, ps) => {
|
|
932
|
-
if (res.writableEnded)
|
|
933
|
-
return;
|
|
934
|
-
const request = req;
|
|
935
|
-
const response = this._customizeResponse(req, res);
|
|
936
|
-
const params = ps;
|
|
937
|
-
const headers = req.headers;
|
|
938
|
-
const query = this._parser.queryString(req.url);
|
|
939
|
-
const xff = headers['x-forwarded-for'];
|
|
940
|
-
const ip = (Array.isArray(xff) ? xff[0] : xff)?.split(',')[0]?.trim()
|
|
941
|
-
|| (Array.isArray(headers['x-real-ip']) ? headers['x-real-ip'][0] : headers['x-real-ip'])
|
|
942
|
-
|| (Array.isArray(headers['cf-connecting-ip']) ? headers['cf-connecting-ip'][0] : headers['cf-connecting-ip'])
|
|
943
|
-
|| null;
|
|
944
750
|
const dispatch = (index = 0) => {
|
|
945
|
-
const
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
const ctx = {
|
|
949
|
-
req: request,
|
|
950
|
-
res: response,
|
|
951
|
-
headers: headers ?? {},
|
|
952
|
-
params: params ?? {},
|
|
953
|
-
query: query ?? {},
|
|
954
|
-
body: body ?? {},
|
|
955
|
-
files: files ?? {},
|
|
956
|
-
cookies: cookies ?? {},
|
|
957
|
-
ip: ip ?? null
|
|
958
|
-
};
|
|
751
|
+
const handler = handlers[index];
|
|
752
|
+
if (!handler)
|
|
753
|
+
return;
|
|
754
|
+
const ctx = this._createContext({ req, res, ps });
|
|
959
755
|
try {
|
|
960
|
-
const
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
return Promise.resolve(this._wrapResponse(handler)(ctx, this._nextFunction(ctx))).catch(err => this._nextFunction(ctx)(err));
|
|
756
|
+
const next = () => dispatch(index + 1);
|
|
757
|
+
const isLast = index === handlers.length - 1;
|
|
758
|
+
if (isLast) {
|
|
759
|
+
return this._wrapResponse(handler)(ctx, this._nextError(ctx));
|
|
965
760
|
}
|
|
966
|
-
return
|
|
761
|
+
return handler(ctx, next);
|
|
967
762
|
}
|
|
968
763
|
catch (err) {
|
|
969
|
-
return this.
|
|
764
|
+
return this._nextError(ctx)(err);
|
|
970
765
|
}
|
|
971
766
|
};
|
|
972
767
|
return dispatch();
|
|
@@ -976,88 +771,47 @@ class Spear {
|
|
|
976
771
|
return (ctx, next) => {
|
|
977
772
|
Promise.resolve(handler(ctx, next))
|
|
978
773
|
.then(result => {
|
|
979
|
-
if (ctx.res.writableEnded)
|
|
774
|
+
if (ctx.res.writableEnded) {
|
|
980
775
|
return;
|
|
776
|
+
}
|
|
981
777
|
if (result instanceof http_1.ServerResponse) {
|
|
982
|
-
if (result?.end) {
|
|
983
|
-
result.end();
|
|
984
|
-
}
|
|
985
778
|
return;
|
|
986
779
|
}
|
|
987
|
-
if (result
|
|
988
|
-
if (!ctx.res.headersSent) {
|
|
989
|
-
ctx.res.writeHead(204, { 'Content-Type': 'text/plain' });
|
|
990
|
-
}
|
|
991
|
-
ctx.res.end();
|
|
780
|
+
if (result instanceof stream_1.Stream) {
|
|
992
781
|
return;
|
|
993
782
|
}
|
|
994
|
-
if (
|
|
995
|
-
ctx.res.
|
|
783
|
+
if (result == null) {
|
|
784
|
+
ctx.res.noContent();
|
|
996
785
|
return;
|
|
997
786
|
}
|
|
998
|
-
if (
|
|
999
|
-
|
|
1000
|
-
if (typeof formattedResult === 'string') {
|
|
1001
|
-
if (!ctx.res.headersSent) {
|
|
1002
|
-
ctx.res.writeHead(200, { 'Content-Type': 'text/plain' });
|
|
1003
|
-
}
|
|
1004
|
-
ctx.res.end(formattedResult);
|
|
1005
|
-
return;
|
|
1006
|
-
}
|
|
1007
|
-
if (!ctx.res.headersSent) {
|
|
1008
|
-
ctx.res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
1009
|
-
}
|
|
1010
|
-
ctx.res.end(JSON.stringify(formattedResult));
|
|
787
|
+
if (typeof result === 'string') {
|
|
788
|
+
ctx.res.send(result);
|
|
1011
789
|
return;
|
|
1012
790
|
}
|
|
1013
|
-
|
|
1014
|
-
ctx.res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
1015
|
-
}
|
|
1016
|
-
ctx.res.end(JSON.stringify(result));
|
|
791
|
+
ctx.res.json(result);
|
|
1017
792
|
return;
|
|
1018
793
|
})
|
|
1019
|
-
.catch(err =>
|
|
1020
|
-
return this._nextFunction(ctx)(err);
|
|
1021
|
-
});
|
|
794
|
+
.catch(err => next(err));
|
|
1022
795
|
};
|
|
1023
796
|
}
|
|
1024
|
-
|
|
797
|
+
_nextError(ctx) {
|
|
1025
798
|
const NEXT_MESSAGE = "The 'next' function does not have any subsequent function.";
|
|
1026
799
|
return (err) => {
|
|
1027
|
-
|
|
1028
|
-
if (this._errorHandler != null) {
|
|
1029
|
-
const callback = this._errorHandler(err, ctx);
|
|
1030
|
-
if (callback == null || !(callback instanceof http_1.ServerResponse)) {
|
|
1031
|
-
ctx.res.writeHead(500, { 'Content-Type': 'application/json' });
|
|
1032
|
-
return ctx.res.end(JSON.stringify({
|
|
1033
|
-
message: err?.message
|
|
1034
|
-
}));
|
|
1035
|
-
}
|
|
1036
|
-
return callback;
|
|
1037
|
-
}
|
|
1038
|
-
ctx.res.writeHead(500, { 'Content-Type': 'application/json' });
|
|
1039
|
-
if (this._formatResponse != null) {
|
|
1040
|
-
return ctx.res.end(JSON.stringify(this._formatResponse({
|
|
1041
|
-
message: err?.message,
|
|
1042
|
-
}, ctx.res.statusCode)));
|
|
1043
|
-
}
|
|
1044
|
-
ctx.res.end(JSON.stringify({
|
|
1045
|
-
message: err?.message
|
|
1046
|
-
}));
|
|
1047
|
-
return;
|
|
1048
|
-
}
|
|
800
|
+
const errorMessage = err?.message || NEXT_MESSAGE;
|
|
1049
801
|
if (this._errorHandler != null) {
|
|
1050
|
-
return this._errorHandler(
|
|
802
|
+
return this._errorHandler(err, ctx);
|
|
803
|
+
}
|
|
804
|
+
if (!ctx.res.headersSent) {
|
|
805
|
+
ctx.res.writeHead(500, const_1.HEADER_CONTENT_TYPES['json']);
|
|
1051
806
|
}
|
|
1052
|
-
ctx.res.writeHead(500, { 'Content-Type': 'application/json' });
|
|
1053
807
|
if (this._formatResponse != null) {
|
|
1054
808
|
ctx.res.end(JSON.stringify(this._formatResponse({
|
|
1055
|
-
message:
|
|
809
|
+
message: errorMessage
|
|
1056
810
|
}, ctx.res.statusCode)));
|
|
1057
811
|
return;
|
|
1058
812
|
}
|
|
1059
813
|
ctx.res.end(JSON.stringify({
|
|
1060
|
-
message:
|
|
814
|
+
message: errorMessage
|
|
1061
815
|
}));
|
|
1062
816
|
return;
|
|
1063
817
|
};
|
|
@@ -1076,7 +830,7 @@ class Spear {
|
|
|
1076
830
|
});
|
|
1077
831
|
}
|
|
1078
832
|
if (cluster_1.default.isWorker) {
|
|
1079
|
-
if (
|
|
833
|
+
if (this._adapter.kind === 'uWS') {
|
|
1080
834
|
const handler = () => {
|
|
1081
835
|
this._onListeners.forEach(listener => listener());
|
|
1082
836
|
if (this._swagger.use) {
|
|
@@ -1114,188 +868,134 @@ class Spear {
|
|
|
1114
868
|
const lookup = this._router.lookup.bind(this._router);
|
|
1115
869
|
const cors = this._cors;
|
|
1116
870
|
const adapter = this._adapter;
|
|
1117
|
-
if ('
|
|
1118
|
-
const server = adapter.App();
|
|
871
|
+
if (adapter.kind === 'uWS') {
|
|
872
|
+
const server = adapter.server.App();
|
|
1119
873
|
server.any('/*', (uwsRes, uwsReq) => {
|
|
1120
|
-
const { req, res } =
|
|
874
|
+
const { req, res } = (0, uWS_1.uWSAdaptRequestResponse)(uwsReq, uwsRes);
|
|
1121
875
|
if (cors)
|
|
1122
876
|
cors(req, res);
|
|
1123
877
|
return lookup(req, res);
|
|
1124
878
|
});
|
|
1125
|
-
if (this._ws) {
|
|
879
|
+
if (this._ws?.handler) {
|
|
1126
880
|
server.ws('/*', {
|
|
1127
881
|
open: (ws) => {
|
|
1128
|
-
this._ws?.connection?.(ws);
|
|
882
|
+
this._ws.handler?.connection?.(ws);
|
|
1129
883
|
},
|
|
1130
884
|
message: (ws, message) => {
|
|
1131
|
-
this._ws?.message?.(ws, Buffer.from(message));
|
|
885
|
+
this._ws.handler?.message?.(ws, Buffer.from(message));
|
|
1132
886
|
},
|
|
1133
887
|
close: (ws, code, message) => {
|
|
1134
|
-
this._ws?.close?.(ws, code, Buffer.from(message));
|
|
888
|
+
this._ws.handler?.close?.(ws, code, Buffer.from(message));
|
|
1135
889
|
}
|
|
1136
890
|
});
|
|
1137
891
|
}
|
|
1138
892
|
return server;
|
|
1139
893
|
}
|
|
894
|
+
if (adapter.kind === 'net') {
|
|
895
|
+
const server = net_1.default.createServer((socket) => {
|
|
896
|
+
(0, net_2.netAdaptRequestResponse)(socket, (req, res) => {
|
|
897
|
+
if (cors)
|
|
898
|
+
cors(req, res);
|
|
899
|
+
return lookup(req, res);
|
|
900
|
+
});
|
|
901
|
+
});
|
|
902
|
+
if (this._ws?.handler) {
|
|
903
|
+
this._ws.server = new ws_1.default.Server({ server, ...this._ws.options });
|
|
904
|
+
this._ws.server.on('connection', (ws) => {
|
|
905
|
+
if (this._ws.handler?.connection) {
|
|
906
|
+
this._ws.handler.connection(ws);
|
|
907
|
+
}
|
|
908
|
+
ws.on('message', (data) => {
|
|
909
|
+
this._ws.handler?.message?.(ws, data);
|
|
910
|
+
});
|
|
911
|
+
ws.on('close', (code, reason) => {
|
|
912
|
+
if (this._ws.handler?.close) {
|
|
913
|
+
this._ws.handler?.close(ws, code, reason);
|
|
914
|
+
}
|
|
915
|
+
});
|
|
916
|
+
ws.on('error', (err) => {
|
|
917
|
+
if (this._ws.handler?.error) {
|
|
918
|
+
this._ws.handler.error(ws, err);
|
|
919
|
+
}
|
|
920
|
+
});
|
|
921
|
+
});
|
|
922
|
+
}
|
|
923
|
+
return server;
|
|
924
|
+
}
|
|
1140
925
|
const server = http_1.default.createServer((req, res) => {
|
|
1141
926
|
if (cors)
|
|
1142
927
|
cors(req, res);
|
|
1143
928
|
return lookup(req, res);
|
|
1144
929
|
});
|
|
1145
|
-
if (this._ws) {
|
|
1146
|
-
this.
|
|
1147
|
-
this.
|
|
1148
|
-
if (this._ws?.connection) {
|
|
1149
|
-
this._ws.connection(ws);
|
|
930
|
+
if (this._ws?.handler) {
|
|
931
|
+
this._ws.server = new ws_1.default.Server({ server, ...this._ws.options });
|
|
932
|
+
this._ws.server.on('connection', (ws) => {
|
|
933
|
+
if (this._ws.handler?.connection) {
|
|
934
|
+
this._ws.handler.connection(ws);
|
|
1150
935
|
}
|
|
1151
936
|
ws.on('message', (data) => {
|
|
1152
|
-
this._ws?.message?.(ws, data);
|
|
937
|
+
this._ws.handler?.message?.(ws, data);
|
|
1153
938
|
});
|
|
1154
939
|
ws.on('close', (code, reason) => {
|
|
1155
|
-
if (this._ws?.close) {
|
|
1156
|
-
this._ws.close(ws, code, reason);
|
|
940
|
+
if (this._ws.handler?.close) {
|
|
941
|
+
this._ws.handler?.close(ws, code, reason);
|
|
1157
942
|
}
|
|
1158
943
|
});
|
|
1159
944
|
ws.on('error', (err) => {
|
|
1160
|
-
if (this._ws?.error) {
|
|
1161
|
-
this._ws.error(ws, err);
|
|
945
|
+
if (this._ws.handler?.error) {
|
|
946
|
+
this._ws.handler.error(ws, err);
|
|
1162
947
|
}
|
|
1163
948
|
});
|
|
1164
949
|
});
|
|
1165
950
|
}
|
|
1166
951
|
return server;
|
|
1167
952
|
}
|
|
1168
|
-
|
|
1169
|
-
const
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
};
|
|
1174
|
-
uwsReq.forEach((key, value) => req.headers[key] = value);
|
|
1175
|
-
const res = {
|
|
1176
|
-
writeHeader: (key, value) => {
|
|
1177
|
-
if (!res.aborted) {
|
|
1178
|
-
uwsRes.writeHeader(key, value);
|
|
1179
|
-
}
|
|
1180
|
-
return res;
|
|
1181
|
-
},
|
|
1182
|
-
setHeader: (key, value) => {
|
|
1183
|
-
if (!res.aborted) {
|
|
1184
|
-
uwsRes.writeHeader(key, value);
|
|
1185
|
-
}
|
|
1186
|
-
return res;
|
|
1187
|
-
},
|
|
1188
|
-
writeHead(status, context) {
|
|
1189
|
-
res.writeHeaders = {
|
|
1190
|
-
...res.writeHeaders,
|
|
1191
|
-
[status]: context
|
|
1192
|
-
};
|
|
1193
|
-
res.headersSent = true;
|
|
1194
|
-
res.statusCode = status;
|
|
1195
|
-
return res;
|
|
1196
|
-
},
|
|
1197
|
-
_writeHead(status, context) {
|
|
1198
|
-
const statusMessages = {
|
|
1199
|
-
100: 'Continue',
|
|
1200
|
-
101: 'Switching Protocols',
|
|
1201
|
-
102: 'Processing',
|
|
1202
|
-
200: 'OK',
|
|
1203
|
-
201: 'Created',
|
|
1204
|
-
202: 'Accepted',
|
|
1205
|
-
203: 'Non-Authoritative Information',
|
|
1206
|
-
204: 'No Content',
|
|
1207
|
-
205: 'Reset Content',
|
|
1208
|
-
206: 'Partial Content',
|
|
1209
|
-
207: 'Multi-Status',
|
|
1210
|
-
208: 'Already Reported',
|
|
1211
|
-
226: 'IM Used',
|
|
1212
|
-
300: 'Multiple Choices',
|
|
1213
|
-
301: 'Moved Permanently',
|
|
1214
|
-
302: 'Found',
|
|
1215
|
-
303: 'See Other',
|
|
1216
|
-
304: 'Not Modified',
|
|
1217
|
-
305: 'Use Proxy',
|
|
1218
|
-
306: '(Unused)',
|
|
1219
|
-
307: 'Temporary Redirect',
|
|
1220
|
-
308: 'Permanent Redirect',
|
|
1221
|
-
400: 'Bad Request',
|
|
1222
|
-
401: 'Unauthorized',
|
|
1223
|
-
402: 'Payment Required',
|
|
1224
|
-
403: 'Forbidden',
|
|
1225
|
-
404: 'Not Found',
|
|
1226
|
-
405: 'Method Not Allowed',
|
|
1227
|
-
406: 'Not Acceptable',
|
|
1228
|
-
407: 'Proxy Authentication Required',
|
|
1229
|
-
408: 'Request Timeout',
|
|
1230
|
-
409: 'Conflict',
|
|
1231
|
-
410: 'Gone',
|
|
1232
|
-
411: 'Length Required',
|
|
1233
|
-
412: 'Precondition Failed',
|
|
1234
|
-
413: 'Payload Too Large',
|
|
1235
|
-
414: 'URI Too Long',
|
|
1236
|
-
415: 'Unsupported Media Type',
|
|
1237
|
-
416: 'Range Not Satisfiable',
|
|
1238
|
-
417: 'Expectation Failed',
|
|
1239
|
-
418: 'I\'m a teapot',
|
|
1240
|
-
421: 'Misdirected Request',
|
|
1241
|
-
422: 'Unprocessable Entity',
|
|
1242
|
-
423: 'Locked',
|
|
1243
|
-
424: 'Failed Dependency',
|
|
1244
|
-
425: 'Too Early',
|
|
1245
|
-
426: 'Upgrade Required',
|
|
1246
|
-
428: 'Precondition Required',
|
|
1247
|
-
429: 'Too Many Requests',
|
|
1248
|
-
431: 'Request Header Fields Too Large',
|
|
1249
|
-
451: 'Unavailable For Legal Reasons',
|
|
1250
|
-
500: 'Internal Server Error',
|
|
1251
|
-
501: 'Not Implemented',
|
|
1252
|
-
502: 'Bad Gateway',
|
|
1253
|
-
503: 'Service Unavailable',
|
|
1254
|
-
504: 'Gateway Timeout',
|
|
1255
|
-
505: 'HTTP Version Not Supported',
|
|
1256
|
-
506: 'Variant Also Negotiates',
|
|
1257
|
-
507: 'Insufficient Storage',
|
|
1258
|
-
508: 'Loop Detected',
|
|
1259
|
-
510: 'Not Extended',
|
|
1260
|
-
511: 'Network Authentication Required'
|
|
1261
|
-
};
|
|
1262
|
-
const statusMessage = statusMessages[status] || statusMessages[500];
|
|
1263
|
-
res.uwsRes.writeStatus(`${status} ${statusMessage}`);
|
|
1264
|
-
res.uwsRes.writeHeader(Object.keys(context)[0], Object.values(context)[0]);
|
|
1265
|
-
return res;
|
|
1266
|
-
},
|
|
1267
|
-
writeStatus: (status) => {
|
|
1268
|
-
if (!res.aborted) {
|
|
1269
|
-
res.uwsRes.writeStatus(status);
|
|
1270
|
-
}
|
|
1271
|
-
return res;
|
|
1272
|
-
},
|
|
1273
|
-
end: (str) => {
|
|
1274
|
-
if (res.aborted) {
|
|
1275
|
-
return;
|
|
1276
|
-
}
|
|
1277
|
-
uwsRes.cork(() => {
|
|
1278
|
-
if (!res.aborted) {
|
|
1279
|
-
res.aborted = true;
|
|
1280
|
-
for (const h in res.writeHeaders) {
|
|
1281
|
-
//@ts-ignore
|
|
1282
|
-
res._writeHead(h, res.writeHeaders[h]);
|
|
1283
|
-
}
|
|
1284
|
-
uwsRes.end(str);
|
|
1285
|
-
return;
|
|
1286
|
-
}
|
|
1287
|
-
});
|
|
1288
|
-
},
|
|
1289
|
-
aborted: false,
|
|
1290
|
-
writeHeaders: {},
|
|
1291
|
-
headersSent: false,
|
|
1292
|
-
statusCode: 200,
|
|
1293
|
-
uwsRes,
|
|
1294
|
-
};
|
|
1295
|
-
uwsRes.onAborted(() => {
|
|
1296
|
-
res.aborted = true;
|
|
953
|
+
_createContext({ req, res, ps }) {
|
|
954
|
+
const request = req;
|
|
955
|
+
const response = (0, response_1.Response)(req, res, {
|
|
956
|
+
formatResponse: this._formatResponse,
|
|
957
|
+
isUwebSocket: this._adapter.kind === 'uWS'
|
|
1297
958
|
});
|
|
1298
|
-
|
|
959
|
+
const headers = req.headers;
|
|
960
|
+
const params = ps;
|
|
961
|
+
const body = request.body;
|
|
962
|
+
const files = request.files;
|
|
963
|
+
const cookies = request.cookies;
|
|
964
|
+
const query = this._parser.queryString(req.url) || {};
|
|
965
|
+
const xff = headers['x-forwarded-for'];
|
|
966
|
+
const xrip = headers['x-real-ip'];
|
|
967
|
+
const cfip = headers['cf-connecting-ip'];
|
|
968
|
+
let ips = [];
|
|
969
|
+
if (cfip) {
|
|
970
|
+
ips = Array.isArray(cfip) ? cfip : [cfip];
|
|
971
|
+
}
|
|
972
|
+
else if (xff) {
|
|
973
|
+
ips = Array.isArray(xff) ? xff : [xff];
|
|
974
|
+
}
|
|
975
|
+
else if (xrip) {
|
|
976
|
+
ips = Array.isArray(xrip) ? xrip : [xrip];
|
|
977
|
+
}
|
|
978
|
+
else {
|
|
979
|
+
const addr = req.socket?.remoteAddress;
|
|
980
|
+
ips = addr ? [addr] : [];
|
|
981
|
+
}
|
|
982
|
+
const ip = (ips.length ? ips[0] : null);
|
|
983
|
+
request.params = params;
|
|
984
|
+
request.query = query;
|
|
985
|
+
request.ip = ip;
|
|
986
|
+
request.ips = ips;
|
|
987
|
+
return {
|
|
988
|
+
req: request,
|
|
989
|
+
res: response,
|
|
990
|
+
headers: headers || Object.create(null),
|
|
991
|
+
params: params || Object.create(null),
|
|
992
|
+
query,
|
|
993
|
+
body: body || Object.create(null),
|
|
994
|
+
files: files || Object.create(null),
|
|
995
|
+
cookies: cookies || Object.create(null),
|
|
996
|
+
ip,
|
|
997
|
+
ips
|
|
998
|
+
};
|
|
1299
999
|
}
|
|
1300
1000
|
_normalizePath(...paths) {
|
|
1301
1001
|
const path = paths
|
|
@@ -1324,8 +1024,8 @@ class Spear {
|
|
|
1324
1024
|
routes
|
|
1325
1025
|
});
|
|
1326
1026
|
this._router.get(staticUrl, staticSwaggerHandler);
|
|
1327
|
-
this._router.get(path, (
|
|
1328
|
-
res.writeHead(200,
|
|
1027
|
+
this._router.get(path, (req, res) => {
|
|
1028
|
+
res.writeHead(200, const_1.HEADER_CONTENT_TYPES['html']);
|
|
1329
1029
|
res.end(html);
|
|
1330
1030
|
return;
|
|
1331
1031
|
});
|