tspace-spear 1.2.3 → 1.2.5
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/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 +34 -37
- package/dist/lib/core/server/index.js +192 -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 +144 -43
- 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 +19 -14
|
@@ -38,14 +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
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 uWS_1 = require("./uWS");
|
|
54
|
+
const net_2 = require("./net");
|
|
49
55
|
/**
|
|
50
56
|
*
|
|
51
57
|
* The 'Spear' class is used to create a server and handle HTTP requests.
|
|
@@ -65,10 +71,10 @@ const parser_factory_1 = require("./parser-factory");
|
|
|
65
71
|
class Spear {
|
|
66
72
|
_controllers;
|
|
67
73
|
_middlewares;
|
|
68
|
-
|
|
69
|
-
_router = (0, find_my_way_1.default)();
|
|
74
|
+
_router = new fast_router_1.FastRouter();
|
|
70
75
|
_parser = new parser_factory_1.ParserFactory();
|
|
71
|
-
|
|
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;
|
|
@@ -103,15 +111,16 @@ class Spear {
|
|
|
103
111
|
}
|
|
104
112
|
};
|
|
105
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
120
|
if (adapter)
|
|
111
121
|
this.useAdater(adapter);
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
this._globalPrefix = globalPrefix == null ? '' : globalPrefix;
|
|
122
|
+
if (globalPrefix)
|
|
123
|
+
this.useGlobalPrefix(globalPrefix);
|
|
115
124
|
}
|
|
116
125
|
/**
|
|
117
126
|
* The get 'instance' method is used to get the instance of Spear.
|
|
@@ -124,7 +133,7 @@ class Spear {
|
|
|
124
133
|
/**
|
|
125
134
|
* The get 'routers' method is used get the all routers.
|
|
126
135
|
*
|
|
127
|
-
* @returns {
|
|
136
|
+
* @returns {FastRouter}
|
|
128
137
|
*/
|
|
129
138
|
get routers() {
|
|
130
139
|
return this._router;
|
|
@@ -137,8 +146,8 @@ class Spear {
|
|
|
137
146
|
* @returns {this}
|
|
138
147
|
*/
|
|
139
148
|
ws(handlers, options) {
|
|
140
|
-
this._ws = handlers();
|
|
141
|
-
this.
|
|
149
|
+
this._ws.handler = handlers();
|
|
150
|
+
this._ws.options = options ?? {};
|
|
142
151
|
return this;
|
|
143
152
|
}
|
|
144
153
|
/**
|
|
@@ -153,16 +162,38 @@ class Spear {
|
|
|
153
162
|
this._globalMiddlewares.push(middleware);
|
|
154
163
|
return this;
|
|
155
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
|
+
}
|
|
156
178
|
/**
|
|
157
179
|
* The 'useAdater' method is used to switch between different server implementations,
|
|
158
180
|
* such as the native Node.js HTTP server or uWebSockets.js (uWS).
|
|
159
181
|
*
|
|
160
|
-
* @param {T.
|
|
182
|
+
* @param {T.AdapterServer} adapter - The adapter instance (e.g., HTTP or uWS).
|
|
161
183
|
* @returns {this} Returns the current instance for chaining
|
|
162
184
|
*/
|
|
163
185
|
useAdater(adapter) {
|
|
164
|
-
|
|
165
|
-
|
|
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);
|
|
166
197
|
return this;
|
|
167
198
|
}
|
|
168
199
|
/**
|
|
@@ -201,13 +232,13 @@ class Spear {
|
|
|
201
232
|
? `\x1b[32m${statusCode}\x1b[0m`
|
|
202
233
|
: `\x1b[31m${statusCode}\x1b[0m`;
|
|
203
234
|
};
|
|
204
|
-
if (exceptPath instanceof RegExp && exceptPath.test(
|
|
235
|
+
if (exceptPath instanceof RegExp && exceptPath.test(req.url))
|
|
205
236
|
return next();
|
|
206
|
-
if (Array.isArray(exceptPath) && exceptPath.some(v =>
|
|
237
|
+
if (Array.isArray(exceptPath) && exceptPath.some(v => req.url === v))
|
|
207
238
|
return next();
|
|
208
239
|
if (methods != null &&
|
|
209
240
|
methods.length &&
|
|
210
|
-
!methods.some(v => v.
|
|
241
|
+
!methods.some(v => v.toLowerCase() === req.method.toLowerCase())) {
|
|
211
242
|
return next();
|
|
212
243
|
}
|
|
213
244
|
const startTime = process.hrtime();
|
|
@@ -216,7 +247,7 @@ class Spear {
|
|
|
216
247
|
`[\x1b[1m\x1b[34mINFO\x1b[0m]`,
|
|
217
248
|
`\x1b[34m${new Date().toJSON()}\x1b[0m`,
|
|
218
249
|
`\x1b[33m${req.method}\x1b[0m`,
|
|
219
|
-
`${decodeURIComponent(
|
|
250
|
+
`${decodeURIComponent(req.url)}`,
|
|
220
251
|
`${statusCode(res)}`,
|
|
221
252
|
`${diffTime(startTime)}`,
|
|
222
253
|
].join(" "));
|
|
@@ -234,28 +265,25 @@ class Spear {
|
|
|
234
265
|
useBodyParser({ except } = {}) {
|
|
235
266
|
this._globalMiddlewares.push((ctx, next) => {
|
|
236
267
|
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())) {
|
|
268
|
+
if (Array.isArray(except) &&
|
|
269
|
+
except.some(v => v.toLowerCase() === (req.method).toLowerCase())) {
|
|
244
270
|
return next();
|
|
245
271
|
}
|
|
246
|
-
|
|
272
|
+
const contentType = req?.headers['content-type'] ?? null;
|
|
273
|
+
if (contentType == null)
|
|
247
274
|
return next();
|
|
248
|
-
|
|
275
|
+
const isFileUpload = contentType && contentType.startsWith('multipart/form-data');
|
|
276
|
+
if (isFileUpload)
|
|
249
277
|
return next();
|
|
250
278
|
if (req?.body != null)
|
|
251
279
|
return next();
|
|
252
280
|
Promise.resolve(this._parser.body(req, res))
|
|
253
|
-
.then(
|
|
254
|
-
req.body =
|
|
281
|
+
.then(body => {
|
|
282
|
+
req.body = body;
|
|
255
283
|
return next();
|
|
256
284
|
})
|
|
257
285
|
.catch(err => {
|
|
258
|
-
return this.
|
|
286
|
+
return this._nextError(ctx)(err);
|
|
259
287
|
});
|
|
260
288
|
});
|
|
261
289
|
return this;
|
|
@@ -264,11 +292,11 @@ class Spear {
|
|
|
264
292
|
* The 'useFileUpload' method is a middleware used to handler file uploads. It adds a file upload of incoming HTTP requests.
|
|
265
293
|
*
|
|
266
294
|
* @param {?Object}
|
|
267
|
-
* @property {?number} limits
|
|
295
|
+
* @property {?number} limits // bytes. default Infinity
|
|
268
296
|
* @property {?string} tempFileDir
|
|
269
297
|
* @property {?Object} removeTempFile
|
|
270
298
|
* @property {boolean} removeTempFile.remove
|
|
271
|
-
* @property {number}
|
|
299
|
+
* @property {number} removeTempFile.ms
|
|
272
300
|
* @returns
|
|
273
301
|
*/
|
|
274
302
|
useFileUpload({ limit, tempFileDir, removeTempFile } = {}) {
|
|
@@ -300,7 +328,7 @@ class Spear {
|
|
|
300
328
|
return next();
|
|
301
329
|
})
|
|
302
330
|
.catch(err => {
|
|
303
|
-
return this.
|
|
331
|
+
return this._nextError(ctx)(err);
|
|
304
332
|
});
|
|
305
333
|
});
|
|
306
334
|
return this;
|
|
@@ -373,7 +401,7 @@ class Spear {
|
|
|
373
401
|
});
|
|
374
402
|
return server;
|
|
375
403
|
}
|
|
376
|
-
if (
|
|
404
|
+
if (this._adapter.kind === 'uWS') {
|
|
377
405
|
const handler = () => {
|
|
378
406
|
this._onListeners.forEach(listener => listener());
|
|
379
407
|
if (this._swagger.use) {
|
|
@@ -469,21 +497,10 @@ class Spear {
|
|
|
469
497
|
*/
|
|
470
498
|
notfound(fn) {
|
|
471
499
|
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
|
-
});
|
|
500
|
+
const ctx = this._createContext({ req, res, ps: {} });
|
|
501
|
+
return fn(ctx);
|
|
483
502
|
};
|
|
484
|
-
this.
|
|
485
|
-
return this.all('*', ...this._globalMiddlewares, handler);
|
|
486
|
-
});
|
|
503
|
+
this.all('*', handler);
|
|
487
504
|
return this;
|
|
488
505
|
}
|
|
489
506
|
/**
|
|
@@ -592,7 +609,7 @@ class Spear {
|
|
|
592
609
|
return this;
|
|
593
610
|
}
|
|
594
611
|
/**
|
|
595
|
-
* The '
|
|
612
|
+
* The 'all' method is used to add the request handler to the router for 'GET' 'POST' 'PUT' 'PATCH' 'DELETE' 'HEAD' 'OPTIONS' methods.
|
|
596
613
|
*
|
|
597
614
|
* @param {string} path
|
|
598
615
|
* @callback {...Function[]} handlers of the middlewares
|
|
@@ -600,21 +617,6 @@ class Spear {
|
|
|
600
617
|
* @property {function} next - go to next function
|
|
601
618
|
* @returns {this}
|
|
602
619
|
*/
|
|
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
620
|
all(path, ...handlers) {
|
|
619
621
|
this._onListeners.push(() => {
|
|
620
622
|
return this._router.all(this._normalizePath(this._globalPrefix, path), this._wrapHandlers(...this._globalMiddlewares, ...handlers));
|
|
@@ -734,239 +736,23 @@ class Spear {
|
|
|
734
736
|
}
|
|
735
737
|
return;
|
|
736
738
|
}
|
|
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
739
|
_wrapHandlers(...handlers) {
|
|
931
740
|
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
741
|
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
|
-
};
|
|
742
|
+
const handler = handlers[index];
|
|
743
|
+
if (!handler)
|
|
744
|
+
return;
|
|
745
|
+
const ctx = this._createContext({ req, res, ps });
|
|
959
746
|
try {
|
|
960
|
-
const
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
return Promise.resolve(this._wrapResponse(handler)(ctx, this._nextFunction(ctx))).catch(err => this._nextFunction(ctx)(err));
|
|
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
|
|
752
|
+
return handler(ctx, next);
|
|
967
753
|
}
|
|
968
754
|
catch (err) {
|
|
969
|
-
return this.
|
|
755
|
+
return this._nextError(ctx)(err);
|
|
970
756
|
}
|
|
971
757
|
};
|
|
972
758
|
return dispatch();
|
|
@@ -976,88 +762,47 @@ class Spear {
|
|
|
976
762
|
return (ctx, next) => {
|
|
977
763
|
Promise.resolve(handler(ctx, next))
|
|
978
764
|
.then(result => {
|
|
979
|
-
if (ctx.res.writableEnded)
|
|
765
|
+
if (ctx.res.writableEnded) {
|
|
980
766
|
return;
|
|
767
|
+
}
|
|
981
768
|
if (result instanceof http_1.ServerResponse) {
|
|
982
|
-
if (result?.end) {
|
|
983
|
-
result.end();
|
|
984
|
-
}
|
|
985
769
|
return;
|
|
986
770
|
}
|
|
987
|
-
if (result
|
|
988
|
-
if (!ctx.res.headersSent) {
|
|
989
|
-
ctx.res.writeHead(204, { 'Content-Type': 'text/plain' });
|
|
990
|
-
}
|
|
991
|
-
ctx.res.end();
|
|
771
|
+
if (result instanceof stream_1.Stream) {
|
|
992
772
|
return;
|
|
993
773
|
}
|
|
994
|
-
if (
|
|
995
|
-
ctx.res.
|
|
774
|
+
if (result == null) {
|
|
775
|
+
ctx.res.noContent();
|
|
996
776
|
return;
|
|
997
777
|
}
|
|
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));
|
|
778
|
+
if (typeof result === 'string') {
|
|
779
|
+
ctx.res.send(result);
|
|
1011
780
|
return;
|
|
1012
781
|
}
|
|
1013
|
-
|
|
1014
|
-
ctx.res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
1015
|
-
}
|
|
1016
|
-
ctx.res.end(JSON.stringify(result));
|
|
782
|
+
ctx.res.json(result);
|
|
1017
783
|
return;
|
|
1018
784
|
})
|
|
1019
|
-
.catch(err =>
|
|
1020
|
-
return this._nextFunction(ctx)(err);
|
|
1021
|
-
});
|
|
785
|
+
.catch(err => next(err));
|
|
1022
786
|
};
|
|
1023
787
|
}
|
|
1024
|
-
|
|
788
|
+
_nextError(ctx) {
|
|
1025
789
|
const NEXT_MESSAGE = "The 'next' function does not have any subsequent function.";
|
|
1026
790
|
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
|
-
}
|
|
791
|
+
const errorMessage = err?.message || NEXT_MESSAGE;
|
|
1049
792
|
if (this._errorHandler != null) {
|
|
1050
|
-
return this._errorHandler(
|
|
793
|
+
return this._errorHandler(err, ctx);
|
|
794
|
+
}
|
|
795
|
+
if (!ctx.res.headersSent) {
|
|
796
|
+
ctx.res.writeHead(500, const_1.HEADER_CONTENT_TYPES['json']);
|
|
1051
797
|
}
|
|
1052
|
-
ctx.res.writeHead(500, { 'Content-Type': 'application/json' });
|
|
1053
798
|
if (this._formatResponse != null) {
|
|
1054
799
|
ctx.res.end(JSON.stringify(this._formatResponse({
|
|
1055
|
-
message:
|
|
800
|
+
message: errorMessage
|
|
1056
801
|
}, ctx.res.statusCode)));
|
|
1057
802
|
return;
|
|
1058
803
|
}
|
|
1059
804
|
ctx.res.end(JSON.stringify({
|
|
1060
|
-
message:
|
|
805
|
+
message: errorMessage
|
|
1061
806
|
}));
|
|
1062
807
|
return;
|
|
1063
808
|
};
|
|
@@ -1076,7 +821,7 @@ class Spear {
|
|
|
1076
821
|
});
|
|
1077
822
|
}
|
|
1078
823
|
if (cluster_1.default.isWorker) {
|
|
1079
|
-
if (
|
|
824
|
+
if (this._adapter.kind === 'uWS') {
|
|
1080
825
|
const handler = () => {
|
|
1081
826
|
this._onListeners.forEach(listener => listener());
|
|
1082
827
|
if (this._swagger.use) {
|
|
@@ -1114,25 +859,56 @@ class Spear {
|
|
|
1114
859
|
const lookup = this._router.lookup.bind(this._router);
|
|
1115
860
|
const cors = this._cors;
|
|
1116
861
|
const adapter = this._adapter;
|
|
1117
|
-
if ('
|
|
1118
|
-
const server = adapter.App();
|
|
862
|
+
if (adapter.kind === 'uWS') {
|
|
863
|
+
const server = adapter.server.App();
|
|
1119
864
|
server.any('/*', (uwsRes, uwsReq) => {
|
|
1120
|
-
const { req, res } =
|
|
865
|
+
const { req, res } = (0, uWS_1.uWSAdaptRequestResponse)(uwsReq, uwsRes);
|
|
1121
866
|
if (cors)
|
|
1122
867
|
cors(req, res);
|
|
1123
868
|
return lookup(req, res);
|
|
1124
869
|
});
|
|
1125
|
-
if (this._ws) {
|
|
870
|
+
if (this._ws?.handler) {
|
|
1126
871
|
server.ws('/*', {
|
|
1127
872
|
open: (ws) => {
|
|
1128
|
-
this._ws?.connection?.(ws);
|
|
873
|
+
this._ws.handler?.connection?.(ws);
|
|
1129
874
|
},
|
|
1130
875
|
message: (ws, message) => {
|
|
1131
|
-
this._ws?.message?.(ws, Buffer.from(message));
|
|
876
|
+
this._ws.handler?.message?.(ws, Buffer.from(message));
|
|
1132
877
|
},
|
|
1133
878
|
close: (ws, code, message) => {
|
|
1134
|
-
this._ws?.close?.(ws, code, Buffer.from(message));
|
|
879
|
+
this._ws.handler?.close?.(ws, code, Buffer.from(message));
|
|
880
|
+
}
|
|
881
|
+
});
|
|
882
|
+
}
|
|
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
|
+
});
|
|
892
|
+
});
|
|
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);
|
|
1135
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
|
+
});
|
|
1136
912
|
});
|
|
1137
913
|
}
|
|
1138
914
|
return server;
|
|
@@ -1142,160 +918,75 @@ class Spear {
|
|
|
1142
918
|
cors(req, res);
|
|
1143
919
|
return lookup(req, res);
|
|
1144
920
|
});
|
|
1145
|
-
if (this._ws) {
|
|
1146
|
-
this.
|
|
1147
|
-
this.
|
|
1148
|
-
if (this._ws?.connection) {
|
|
1149
|
-
this._ws.connection(ws);
|
|
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);
|
|
1150
926
|
}
|
|
1151
927
|
ws.on('message', (data) => {
|
|
1152
|
-
this._ws?.message?.(ws, data);
|
|
928
|
+
this._ws.handler?.message?.(ws, data);
|
|
1153
929
|
});
|
|
1154
930
|
ws.on('close', (code, reason) => {
|
|
1155
|
-
if (this._ws?.close) {
|
|
1156
|
-
this._ws.close(ws, code, reason);
|
|
931
|
+
if (this._ws.handler?.close) {
|
|
932
|
+
this._ws.handler?.close(ws, code, reason);
|
|
1157
933
|
}
|
|
1158
934
|
});
|
|
1159
935
|
ws.on('error', (err) => {
|
|
1160
|
-
if (this._ws?.error) {
|
|
1161
|
-
this._ws.error(ws, err);
|
|
936
|
+
if (this._ws.handler?.error) {
|
|
937
|
+
this._ws.handler.error(ws, err);
|
|
1162
938
|
}
|
|
1163
939
|
});
|
|
1164
940
|
});
|
|
1165
941
|
}
|
|
1166
942
|
return server;
|
|
1167
943
|
}
|
|
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;
|
|
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'
|
|
1297
949
|
});
|
|
1298
|
-
|
|
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
|
+
};
|
|
1299
990
|
}
|
|
1300
991
|
_normalizePath(...paths) {
|
|
1301
992
|
const path = paths
|
|
@@ -1324,8 +1015,8 @@ class Spear {
|
|
|
1324
1015
|
routes
|
|
1325
1016
|
});
|
|
1326
1017
|
this._router.get(staticUrl, staticSwaggerHandler);
|
|
1327
|
-
this._router.get(path, (
|
|
1328
|
-
res.writeHead(200,
|
|
1018
|
+
this._router.get(path, (req, res) => {
|
|
1019
|
+
res.writeHead(200, const_1.HEADER_CONTENT_TYPES['html']);
|
|
1329
1020
|
res.end(html);
|
|
1330
1021
|
return;
|
|
1331
1022
|
});
|