ultimate-express 1.2.0 → 1.2.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/package.json +1 -1
- package/src/application.js +4 -15
- package/src/router.js +66 -49
- package/src/utils.js +25 -1
package/package.json
CHANGED
package/src/application.js
CHANGED
|
@@ -178,23 +178,12 @@ class Application extends Router {
|
|
|
178
178
|
|
|
179
179
|
#createRequestHandler() {
|
|
180
180
|
this.uwsApp.any('/*', async (res, req) => {
|
|
181
|
-
const request =
|
|
182
|
-
const response = new this._response(res, request, this);
|
|
183
|
-
request.res = response;
|
|
184
|
-
response.req = request;
|
|
185
|
-
|
|
186
|
-
res.onAborted(() => {
|
|
187
|
-
const err = new Error('Request aborted');
|
|
188
|
-
err.code = 'ECONNABORTED';
|
|
189
|
-
response.aborted = true;
|
|
190
|
-
response.socket.emit('error', err);
|
|
191
|
-
});
|
|
192
|
-
|
|
193
|
-
let matchedRoute = await this._routeRequest(request, response);
|
|
181
|
+
const { request, response } = this.handleRequest(res, req);
|
|
194
182
|
|
|
195
|
-
|
|
183
|
+
const matchedRoute = await this._routeRequest(request, response);
|
|
184
|
+
if(!matchedRoute && !response.headersSent && !response.aborted) {
|
|
196
185
|
response.status(404);
|
|
197
|
-
response.send(this._generateErrorPage(`Cannot ${request.method} ${request.path}
|
|
186
|
+
response.send(this._generateErrorPage(`Cannot ${request.method} ${request.path}`, false));
|
|
198
187
|
}
|
|
199
188
|
});
|
|
200
189
|
}
|
package/src/router.js
CHANGED
|
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
|
|
14
14
|
limitations under the License.
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
|
-
const { patternToRegex, needsConversionToRegex, deprecated, findIndexStartingFrom } = require("./utils.js");
|
|
17
|
+
const { patternToRegex, needsConversionToRegex, deprecated, findIndexStartingFrom, canBeOptimized } = require("./utils.js");
|
|
18
18
|
const Response = require("./response.js");
|
|
19
19
|
const Request = require("./request.js");
|
|
20
20
|
const { EventEmitter } = require("tseep");
|
|
@@ -138,7 +138,7 @@ module.exports = class Router extends EventEmitter {
|
|
|
138
138
|
};
|
|
139
139
|
routes.push(route);
|
|
140
140
|
// normal routes optimization
|
|
141
|
-
if(
|
|
141
|
+
if(canBeOptimized(route.path) && route.pattern !== '/*' && !this.parent && this.get('case sensitive routing') && this.uwsApp) {
|
|
142
142
|
if(supportedUwsMethods.includes(method)) {
|
|
143
143
|
const optimizedPath = this.#optimizeRoute(route, this._routes);
|
|
144
144
|
if(optimizedPath) {
|
|
@@ -185,7 +185,8 @@ module.exports = class Router extends EventEmitter {
|
|
|
185
185
|
this.#registerUwsRoute({
|
|
186
186
|
...cbroute,
|
|
187
187
|
path: route.path + cbroute.path,
|
|
188
|
-
pattern: route.path + cbroute.path
|
|
188
|
+
pattern: route.path + cbroute.path,
|
|
189
|
+
optimizedRouter: true
|
|
189
190
|
}, optimizedPath);
|
|
190
191
|
}
|
|
191
192
|
}
|
|
@@ -239,6 +240,21 @@ module.exports = class Router extends EventEmitter {
|
|
|
239
240
|
return optimizedPath;
|
|
240
241
|
}
|
|
241
242
|
|
|
243
|
+
handleRequest(res, req) {
|
|
244
|
+
const request = new this._request(req, res, this);
|
|
245
|
+
const response = new this._response(res, request, this);
|
|
246
|
+
request.res = response;
|
|
247
|
+
response.req = request;
|
|
248
|
+
res.onAborted(() => {
|
|
249
|
+
const err = new Error('Connection closed');
|
|
250
|
+
err.code = 'ECONNRESET';
|
|
251
|
+
response.aborted = true;
|
|
252
|
+
response.socket.emit('error', err);
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
return { request, response };
|
|
256
|
+
}
|
|
257
|
+
|
|
242
258
|
#registerUwsRoute(route, optimizedPath) {
|
|
243
259
|
let method = route.method.toLowerCase();
|
|
244
260
|
if(method === 'all') {
|
|
@@ -246,35 +262,34 @@ module.exports = class Router extends EventEmitter {
|
|
|
246
262
|
} else if(method === 'delete') {
|
|
247
263
|
method = 'del';
|
|
248
264
|
}
|
|
265
|
+
if(!route.optimizedRouter && route.path.includes(":")) {
|
|
266
|
+
route.optimizedParams = route.path.match(/:(\w+)/g).map(p => p.slice(1));
|
|
267
|
+
}
|
|
249
268
|
const fn = async (res, req) => {
|
|
250
|
-
const request =
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
const routed = await this._routeRequest(request, response, 0, optimizedPath, true, route);
|
|
262
|
-
if(routed) {
|
|
263
|
-
return;
|
|
269
|
+
const { request, response } = this.handleRequest(res, req);
|
|
270
|
+
if(route.optimizedParams) {
|
|
271
|
+
request.optimizedParams = {};
|
|
272
|
+
for(let i = 0; i < route.optimizedParams.length; i++) {
|
|
273
|
+
request.optimizedParams[route.optimizedParams[i]] = req.getParameter(i);
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
const matchedRoute = await this._routeRequest(request, response, 0, optimizedPath, true, route);
|
|
277
|
+
if(!matchedRoute && !response.headersSent && !response.aborted) {
|
|
278
|
+
response.status(404);
|
|
279
|
+
response.send(this._generateErrorPage(`Cannot ${request.method} ${request.path}`, false));
|
|
264
280
|
}
|
|
265
|
-
response.status(404);
|
|
266
|
-
response.send(this._generateErrorPage(`Cannot ${request.method} ${request.path}`, false));
|
|
267
281
|
};
|
|
268
282
|
route.optimizedPath = optimizedPath;
|
|
269
|
-
|
|
283
|
+
let replacedPath = route.path.replace(/:(\w+)/g, ':x');
|
|
284
|
+
this.uwsApp[method](replacedPath, fn);
|
|
270
285
|
if(!this.get('strict routing') && route.path[route.path.length - 1] !== '/') {
|
|
271
|
-
this.uwsApp[method](
|
|
286
|
+
this.uwsApp[method](replacedPath + '/', fn);
|
|
272
287
|
if(method === 'get') {
|
|
273
|
-
this.uwsApp.head(
|
|
288
|
+
this.uwsApp.head(replacedPath + '/', fn);
|
|
274
289
|
}
|
|
275
290
|
}
|
|
276
291
|
if(method === 'get') {
|
|
277
|
-
this.uwsApp.head(
|
|
292
|
+
this.uwsApp.head(replacedPath, fn);
|
|
278
293
|
}
|
|
279
294
|
}
|
|
280
295
|
|
|
@@ -313,7 +328,9 @@ module.exports = class Router extends EventEmitter {
|
|
|
313
328
|
#preprocessRequest(req, res, route) {
|
|
314
329
|
return new Promise(async resolve => {
|
|
315
330
|
req.route = route;
|
|
316
|
-
if(
|
|
331
|
+
if(route.optimizedParams) {
|
|
332
|
+
req.params = req.optimizedParams;
|
|
333
|
+
} else if(typeof route.path === 'string' && (route.path.includes(':') || route.path.includes('*')) && route.pattern instanceof RegExp) {
|
|
317
334
|
let path = req.path;
|
|
318
335
|
if(req._stack.length > 0) {
|
|
319
336
|
path = path.replace(this.getFullMountpath(req), '');
|
|
@@ -324,31 +341,6 @@ module.exports = class Router extends EventEmitter {
|
|
|
324
341
|
req.params = {...params, ...req.params};
|
|
325
342
|
}
|
|
326
343
|
}
|
|
327
|
-
|
|
328
|
-
for(let param in req.params) {
|
|
329
|
-
if(this.#paramCallbacks.has(param) && !req._gotParams.has(param)) {
|
|
330
|
-
req._gotParams.add(param);
|
|
331
|
-
const pcs = this.#paramCallbacks.get(param);
|
|
332
|
-
for(let i = 0; i < pcs.length; i++) {
|
|
333
|
-
const fn = pcs[i];
|
|
334
|
-
await new Promise(resolveRoute => {
|
|
335
|
-
const next = (thingamabob) => {
|
|
336
|
-
if(thingamabob) {
|
|
337
|
-
if(thingamabob === 'route') {
|
|
338
|
-
return resolve('route');
|
|
339
|
-
} else {
|
|
340
|
-
this.#handleError(thingamabob, req, res);
|
|
341
|
-
return resolve(false);
|
|
342
|
-
}
|
|
343
|
-
}
|
|
344
|
-
return resolveRoute();
|
|
345
|
-
};
|
|
346
|
-
req.next = next;
|
|
347
|
-
fn(req, res, next, req.params[param], param);
|
|
348
|
-
});
|
|
349
|
-
}
|
|
350
|
-
}
|
|
351
|
-
}
|
|
352
344
|
} else {
|
|
353
345
|
req.params = {};
|
|
354
346
|
if(req._paramStack.length > 0) {
|
|
@@ -358,6 +350,31 @@ module.exports = class Router extends EventEmitter {
|
|
|
358
350
|
}
|
|
359
351
|
}
|
|
360
352
|
|
|
353
|
+
for(let param in req.params) {
|
|
354
|
+
if(this.#paramCallbacks.has(param) && !req._gotParams.has(param)) {
|
|
355
|
+
req._gotParams.add(param);
|
|
356
|
+
const pcs = this.#paramCallbacks.get(param);
|
|
357
|
+
for(let i = 0; i < pcs.length; i++) {
|
|
358
|
+
const fn = pcs[i];
|
|
359
|
+
await new Promise(resolveRoute => {
|
|
360
|
+
const next = (thingamabob) => {
|
|
361
|
+
if(thingamabob) {
|
|
362
|
+
if(thingamabob === 'route') {
|
|
363
|
+
return resolve('route');
|
|
364
|
+
} else {
|
|
365
|
+
this.#handleError(thingamabob, req, res);
|
|
366
|
+
return resolve(false);
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
return resolveRoute();
|
|
370
|
+
};
|
|
371
|
+
req.next = next;
|
|
372
|
+
fn(req, res, next, req.params[param], param);
|
|
373
|
+
});
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
|
|
361
378
|
resolve(true);
|
|
362
379
|
});
|
|
363
380
|
}
|
package/src/utils.js
CHANGED
|
@@ -74,6 +74,29 @@ function needsConversionToRegex(pattern) {
|
|
|
74
74
|
pattern.includes(']');
|
|
75
75
|
}
|
|
76
76
|
|
|
77
|
+
function canBeOptimized(pattern) {
|
|
78
|
+
if(pattern === '/*') {
|
|
79
|
+
return false;
|
|
80
|
+
}
|
|
81
|
+
if(pattern instanceof RegExp) {
|
|
82
|
+
return false;
|
|
83
|
+
}
|
|
84
|
+
if(
|
|
85
|
+
pattern.includes('*') ||
|
|
86
|
+
pattern.includes('?') ||
|
|
87
|
+
pattern.includes('+') ||
|
|
88
|
+
pattern.includes('(') ||
|
|
89
|
+
pattern.includes(')') ||
|
|
90
|
+
pattern.includes('{') ||
|
|
91
|
+
pattern.includes('}') ||
|
|
92
|
+
pattern.includes('[') ||
|
|
93
|
+
pattern.includes(']')
|
|
94
|
+
) {
|
|
95
|
+
return false;
|
|
96
|
+
}
|
|
97
|
+
return true;
|
|
98
|
+
}
|
|
99
|
+
|
|
77
100
|
function acceptParams(str) {
|
|
78
101
|
const parts = str.split(/ *; */);
|
|
79
102
|
const ret = { value: parts[0], quality: 1, params: {} }
|
|
@@ -311,5 +334,6 @@ module.exports = {
|
|
|
311
334
|
createETagGenerator,
|
|
312
335
|
isRangeFresh,
|
|
313
336
|
findIndexStartingFrom,
|
|
314
|
-
fastQueryParse
|
|
337
|
+
fastQueryParse,
|
|
338
|
+
canBeOptimized
|
|
315
339
|
};
|