@ndiinginc/router 4.11.2 → 4.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/rest/router.http +4 -0
- package/src/app.js +1 -2
- package/src/index.js +2 -0
- package/src/middleware/urlencoded.js +44 -0
- package/src/router.js +4 -28
- package/src/util.js +24 -35
package/package.json
CHANGED
package/rest/router.http
CHANGED
package/src/app.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
const http = require("http");
|
|
2
|
-
const { EMPTY_PARAMS } = require("./util");
|
|
3
2
|
const { Router } = require("./router");
|
|
4
3
|
const { Request } = require("./request");
|
|
5
4
|
const { Response } = require("./response");
|
|
@@ -67,7 +66,7 @@ class App extends Router {
|
|
|
67
66
|
*/
|
|
68
67
|
async handle(req, res) {
|
|
69
68
|
const { params, paramsLength, handlers, errorHandlers } = this.find(req.method, req.path);
|
|
70
|
-
req.params = paramsLength ? Object.assign(Object.create(null), params) :
|
|
69
|
+
req.params = paramsLength ? Object.assign(Object.create(null), params) : Object.create(null);
|
|
71
70
|
let err;
|
|
72
71
|
try {
|
|
73
72
|
const handlerPromise = async () => {
|
package/src/index.js
CHANGED
|
@@ -3,9 +3,11 @@ const { App } = require("./app");
|
|
|
3
3
|
const { Router } = require("./router");
|
|
4
4
|
const { json } = require("./middleware/json");
|
|
5
5
|
const { cors } = require("./middleware/cors");
|
|
6
|
+
const { urlencoded } = require("./middleware/urlencoded");
|
|
6
7
|
|
|
7
8
|
App.Router = Router;
|
|
8
9
|
App.json = json;
|
|
9
10
|
App.cors = cors;
|
|
11
|
+
App.urlencoded = urlencoded;
|
|
10
12
|
|
|
11
13
|
module.exports = App;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
const http = require("http");
|
|
2
|
+
const { parseQueryString } = require("../util");
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @typedef {Object} Options
|
|
6
|
+
* @property {Number} [limit=1.024e+5]
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* @param {Options} Options
|
|
11
|
+
* @returns {Callback}
|
|
12
|
+
*/
|
|
13
|
+
function urlencoded({ limit = 1.024e5 } = {}) {
|
|
14
|
+
return async (req, res) => {
|
|
15
|
+
if (!["POST", "PUT", "PATCH", "QUERY"].includes(req.method)) {
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
const contentType = req.headers["content-type"];
|
|
19
|
+
if (!contentType || !contentType.includes("application/x-www-form-urlencoded")) {
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
const contentLength = parseInt(req.headers["content-length"], 10);
|
|
23
|
+
if (contentLength && contentLength > limit) {
|
|
24
|
+
res.statusCode = 413;
|
|
25
|
+
throw new Error(http.STATUS_CODES[res.statusCode]);
|
|
26
|
+
}
|
|
27
|
+
let chunkLength = 0;
|
|
28
|
+
const chunks = [];
|
|
29
|
+
for await (const chunk of req) {
|
|
30
|
+
chunkLength += chunk.length;
|
|
31
|
+
if (chunkLength > limit) {
|
|
32
|
+
res.statusCode = 413;
|
|
33
|
+
throw new Error(http.STATUS_CODES[res.statusCode]);
|
|
34
|
+
}
|
|
35
|
+
chunks.push(chunk);
|
|
36
|
+
}
|
|
37
|
+
if (chunks.length === 0) {
|
|
38
|
+
req.body = null;
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
req.body = parseQueryString(Buffer.concat(chunks).toString("utf8"));
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
exports.urlencoded = urlencoded;
|
package/src/router.js
CHANGED
|
@@ -189,32 +189,14 @@ class Router {
|
|
|
189
189
|
}
|
|
190
190
|
const segment = segments[index];
|
|
191
191
|
if (node.children.has(segment)) {
|
|
192
|
-
const res = this.search(
|
|
193
|
-
//
|
|
194
|
-
method,
|
|
195
|
-
segments,
|
|
196
|
-
node.children.get(segment),
|
|
197
|
-
path,
|
|
198
|
-
params,
|
|
199
|
-
state,
|
|
200
|
-
index + 1,
|
|
201
|
-
);
|
|
192
|
+
const res = this.search(method, segments, node.children.get(segment), path, params, state, index + 1);
|
|
202
193
|
if (res.matched) return res;
|
|
203
194
|
}
|
|
204
195
|
if (node.params.size) {
|
|
205
196
|
for (const [, child] of node.params) {
|
|
206
197
|
const prev = params[child.name];
|
|
207
198
|
params[child.name] = decodeParam(segment);
|
|
208
|
-
const res = this.search(
|
|
209
|
-
//
|
|
210
|
-
method,
|
|
211
|
-
segments,
|
|
212
|
-
child,
|
|
213
|
-
path,
|
|
214
|
-
params,
|
|
215
|
-
state,
|
|
216
|
-
index + 1,
|
|
217
|
-
);
|
|
199
|
+
const res = this.search(method, segments, child, path, params, state, index + 1);
|
|
218
200
|
if (res.matched) return res;
|
|
219
201
|
if (prev === undefined) {
|
|
220
202
|
const { [child.name]: _, ...rest } = params;
|
|
@@ -223,8 +205,7 @@ class Router {
|
|
|
223
205
|
}
|
|
224
206
|
}
|
|
225
207
|
if (node.wildcard && (node.wildcard.handlers.get(method) || node.wildcard.handlers.get("ALL"))) {
|
|
226
|
-
|
|
227
|
-
params["wildcard"] = decodeParam(rest);
|
|
208
|
+
params["wildcard"] = segments.slice(index).map(decodeParam).join("/");
|
|
228
209
|
path.push(node.wildcard);
|
|
229
210
|
return { path, params, matched: true };
|
|
230
211
|
}
|
|
@@ -265,12 +246,7 @@ class Router {
|
|
|
265
246
|
* @returns {{matched: boolean;params: Object;paramsLength: number;handlers: any[];errorHandlers: any[];}}
|
|
266
247
|
*/
|
|
267
248
|
find(method, path) {
|
|
268
|
-
const res = this.search(
|
|
269
|
-
//
|
|
270
|
-
method,
|
|
271
|
-
this.split(path),
|
|
272
|
-
this.root,
|
|
273
|
-
);
|
|
249
|
+
const res = this.search(method, this.split(path), this.root);
|
|
274
250
|
const handlers = {};
|
|
275
251
|
const errorHandlers = {};
|
|
276
252
|
for (const r of res.path) {
|
package/src/util.js
CHANGED
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
const EMPTY_PARAMS = Object.create(null);
|
|
2
|
-
exports.EMPTY_PARAMS = EMPTY_PARAMS;
|
|
3
|
-
|
|
4
1
|
/**
|
|
5
2
|
* @param {String} raw
|
|
6
3
|
* @returns {String}
|
|
@@ -14,39 +11,21 @@ function decodeParam(raw) {
|
|
|
14
11
|
}
|
|
15
12
|
exports.decodeParam = decodeParam;
|
|
16
13
|
|
|
17
|
-
/**
|
|
18
|
-
* @param {String} raw
|
|
19
|
-
* @returns {String}
|
|
20
|
-
*/
|
|
21
|
-
function decodeQuery(raw) {
|
|
22
|
-
const normalized = raw.replace(/\+/g, " ");
|
|
23
|
-
try {
|
|
24
|
-
return decodeURIComponent(normalized);
|
|
25
|
-
} catch (error) {
|
|
26
|
-
return normalized;
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
|
|
30
14
|
/**
|
|
31
15
|
* @param {String} queryString
|
|
32
16
|
* @returns {Object}
|
|
33
17
|
*/
|
|
34
18
|
function parseQueryString(queryString) {
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
if (Object.hasOwn(result, name)) {
|
|
44
|
-
if (Array.isArray(result[name])) result[name].push(value);
|
|
45
|
-
else result[name] = [result[name], value];
|
|
46
|
-
} else result[name] = value;
|
|
19
|
+
const query = Object.create(null);
|
|
20
|
+
if (queryString) {
|
|
21
|
+
for (const [name, value] of new URLSearchParams(queryString)) {
|
|
22
|
+
if (Object.hasOwn(query, name)) {
|
|
23
|
+
if (Array.isArray(query[name])) query[name].push(value);
|
|
24
|
+
else query[name] = [query[name], value];
|
|
25
|
+
} else query[name] = value;
|
|
26
|
+
}
|
|
47
27
|
}
|
|
48
|
-
|
|
49
|
-
return result;
|
|
28
|
+
return query;
|
|
50
29
|
}
|
|
51
30
|
exports.parseQueryString = parseQueryString;
|
|
52
31
|
|
|
@@ -55,11 +34,21 @@ exports.parseQueryString = parseQueryString;
|
|
|
55
34
|
* @returns {{path: any;queryString: any;}}
|
|
56
35
|
*/
|
|
57
36
|
function parseUrl(url) {
|
|
58
|
-
|
|
59
|
-
|
|
37
|
+
let path = url;
|
|
38
|
+
let queryString = "";
|
|
39
|
+
let hash = "";
|
|
40
|
+
if (url.includes("?") || url.includes("#")) {
|
|
41
|
+
const hashIdx = url.indexOf("#");
|
|
42
|
+
if (hashIdx !== -1) {
|
|
43
|
+
hash = url.slice(hashIdx + 1);
|
|
44
|
+
path = url.slice(0, hashIdx);
|
|
45
|
+
}
|
|
46
|
+
const queryIdx = path.indexOf("?");
|
|
47
|
+
if (queryIdx !== -1) {
|
|
48
|
+
queryString = path.slice(queryIdx + 1);
|
|
49
|
+
path = path.slice(0, queryIdx);
|
|
50
|
+
}
|
|
60
51
|
}
|
|
61
|
-
|
|
62
|
-
const [, path = "/", , queryString = ""] = regex.exec(url);
|
|
63
|
-
return { path, queryString };
|
|
52
|
+
return { path, queryString, hash };
|
|
64
53
|
}
|
|
65
54
|
exports.parseUrl = parseUrl;
|