@e22m4u/js-trie-router 0.2.1 → 0.3.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/README.md +3 -3
- package/dist/cjs/index.cjs +225 -213
- package/examples/{cookie-parsing-example.js → cookies-parsing-example.js} +8 -8
- package/examples/params-parsing-example.js +11 -7
- package/examples/query-parsing-example.js +11 -7
- package/examples/uptime-example.js +4 -4
- package/package.json +8 -7
- package/src/debuggable-service.d.ts +2 -10
- package/src/debuggable-service.js +16 -17
- package/src/hooks/hook-invoker.js +3 -4
- package/src/hooks/hook-invoker.spec.js +3 -3
- package/src/hooks/hook-registry.d.ts +1 -1
- package/src/hooks/hook-registry.js +6 -7
- package/src/hooks/hook-registry.spec.js +14 -5
- package/src/parsers/body-parser.js +10 -11
- package/src/parsers/body-parser.spec.js +4 -4
- package/src/parsers/cookies-parser.d.ts +15 -0
- package/src/parsers/cookies-parser.js +33 -0
- package/src/parsers/{cookie-parser.spec.js → cookies-parser.spec.js} +6 -6
- package/src/parsers/index.d.ts +1 -1
- package/src/parsers/index.js +1 -1
- package/src/parsers/query-parser.js +4 -3
- package/src/parsers/request-parser.d.ts +2 -2
- package/src/parsers/request-parser.js +7 -7
- package/src/parsers/request-parser.spec.js +12 -12
- package/src/request-context.d.ts +3 -3
- package/src/request-context.js +5 -5
- package/src/request-context.spec.js +3 -3
- package/src/route-registry.js +14 -14
- package/src/route-registry.spec.js +4 -1
- package/src/route.d.ts +12 -7
- package/src/route.js +16 -14
- package/src/route.spec.js +13 -7
- package/src/router-options.js +1 -1
- package/src/router-options.spec.js +1 -1
- package/src/senders/data-sender.js +6 -5
- package/src/senders/error-sender.js +11 -4
- package/src/trie-router.js +46 -38
- package/src/trie-router.spec.js +54 -3
- package/src/utils/create-cookies-string.d.ts +6 -0
- package/src/utils/{create-cookie-string.js → create-cookies-string.js} +4 -4
- package/src/utils/{create-cookie-string.spec.js → create-cookies-string.spec.js} +7 -7
- package/src/utils/create-debugger.js +1 -1
- package/src/utils/create-debugger.spec.js +1 -1
- package/src/utils/create-error.js +2 -2
- package/src/utils/create-error.spec.js +2 -2
- package/src/utils/create-request-mock.d.ts +1 -1
- package/src/utils/create-request-mock.js +47 -43
- package/src/utils/create-request-mock.spec.js +18 -18
- package/src/utils/fetch-request-body.d.ts +11 -2
- package/src/utils/fetch-request-body.js +10 -17
- package/src/utils/fetch-request-body.spec.js +8 -9
- package/src/utils/get-request-pathname.js +1 -1
- package/src/utils/get-request-pathname.spec.js +1 -1
- package/src/utils/index.d.ts +2 -2
- package/src/utils/index.js +2 -2
- package/src/utils/is-readable-stream.js +1 -2
- package/src/utils/is-response-sent.js +1 -1
- package/src/utils/is-response-sent.spec.js +1 -1
- package/src/utils/parse-content-type.js +1 -1
- package/src/utils/parse-cookies.d.ts +19 -0
- package/src/utils/{parse-cookie.js → parse-cookies.js} +8 -5
- package/src/utils/{parse-cookie.spec.js → parse-cookies.spec.js} +13 -8
- package/src/utils/to-camel-case.js +1 -1
- package/src/utils/to-camel-case.spec.js +1 -1
- package/src/parsers/cookie-parser.d.ts +0 -15
- package/src/parsers/cookie-parser.js +0 -32
- package/src/utils/create-cookie-string.d.ts +0 -6
- package/src/utils/parse-cookie.d.ts +0 -19
package/dist/cjs/index.cjs
CHANGED
|
@@ -31,9 +31,9 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
31
31
|
// src/index.js
|
|
32
32
|
var index_exports = {};
|
|
33
33
|
__export(index_exports, {
|
|
34
|
-
BUFFER_ENCODING_LIST: () => BUFFER_ENCODING_LIST,
|
|
35
34
|
BodyParser: () => BodyParser,
|
|
36
|
-
|
|
35
|
+
CHARACTER_ENCODING_LIST: () => CHARACTER_ENCODING_LIST,
|
|
36
|
+
CookiesParser: () => CookiesParser,
|
|
37
37
|
DataSender: () => DataSender,
|
|
38
38
|
EXPOSED_ERROR_PROPERTIES: () => EXPOSED_ERROR_PROPERTIES,
|
|
39
39
|
ErrorSender: () => ErrorSender,
|
|
@@ -50,7 +50,7 @@ __export(index_exports, {
|
|
|
50
50
|
RouterOptions: () => RouterOptions,
|
|
51
51
|
TrieRouter: () => TrieRouter,
|
|
52
52
|
UNPARSABLE_MEDIA_TYPES: () => UNPARSABLE_MEDIA_TYPES,
|
|
53
|
-
|
|
53
|
+
createCookiesString: () => createCookiesString,
|
|
54
54
|
createDebugger: () => createDebugger,
|
|
55
55
|
createError: () => createError,
|
|
56
56
|
createRequestMock: () => createRequestMock,
|
|
@@ -62,7 +62,7 @@ __export(index_exports, {
|
|
|
62
62
|
isResponseSent: () => isResponseSent,
|
|
63
63
|
isWritableStream: () => isWritableStream,
|
|
64
64
|
parseContentType: () => parseContentType,
|
|
65
|
-
|
|
65
|
+
parseCookies: () => parseCookies,
|
|
66
66
|
parseJsonBody: () => parseJsonBody,
|
|
67
67
|
toCamelCase: () => toCamelCase
|
|
68
68
|
});
|
|
@@ -82,48 +82,49 @@ function isPromise(value) {
|
|
|
82
82
|
}
|
|
83
83
|
__name(isPromise, "isPromise");
|
|
84
84
|
|
|
85
|
-
// src/utils/parse-cookie.js
|
|
86
|
-
var import_js_format = require("@e22m4u/js-format");
|
|
87
|
-
function parseCookie(input) {
|
|
88
|
-
if (typeof input !== "string")
|
|
89
|
-
throw new import_js_format.Errorf(
|
|
90
|
-
'The first parameter of "parseCookie" should be a String, but %v given.',
|
|
91
|
-
input
|
|
92
|
-
);
|
|
93
|
-
return input.split(";").filter((v) => v !== "").map((v) => v.split("=")).reduce((cookies, tuple) => {
|
|
94
|
-
const key = decodeURIComponent(tuple[0]).trim();
|
|
95
|
-
cookies[key] = decodeURIComponent(tuple[1]).trim();
|
|
96
|
-
return cookies;
|
|
97
|
-
}, {});
|
|
98
|
-
}
|
|
99
|
-
__name(parseCookie, "parseCookie");
|
|
100
|
-
|
|
101
85
|
// src/utils/create-error.js
|
|
86
|
+
var import_js_format = require("@e22m4u/js-format");
|
|
102
87
|
var import_js_format2 = require("@e22m4u/js-format");
|
|
103
|
-
var import_js_format3 = require("@e22m4u/js-format");
|
|
104
88
|
function createError(errorCtor, message, ...args) {
|
|
105
89
|
if (typeof errorCtor !== "function")
|
|
106
|
-
throw new
|
|
107
|
-
'The first argument of "createError" should be a constructor, but %v given.',
|
|
90
|
+
throw new import_js_format2.Errorf(
|
|
91
|
+
'The first argument of "createError" should be a constructor, but %v was given.',
|
|
108
92
|
errorCtor
|
|
109
93
|
);
|
|
110
94
|
if (message != null && typeof message !== "string")
|
|
111
|
-
throw new
|
|
112
|
-
'The second argument of "createError" should be a String, but %v given.',
|
|
95
|
+
throw new import_js_format2.Errorf(
|
|
96
|
+
'The second argument of "createError" should be a String, but %v was given.',
|
|
113
97
|
message
|
|
114
98
|
);
|
|
115
99
|
if (message == null) return new errorCtor();
|
|
116
|
-
const interpolatedMessage = (0,
|
|
100
|
+
const interpolatedMessage = (0, import_js_format.format)(message, ...args);
|
|
117
101
|
return new errorCtor(interpolatedMessage);
|
|
118
102
|
}
|
|
119
103
|
__name(createError, "createError");
|
|
120
104
|
|
|
105
|
+
// src/utils/parse-cookies.js
|
|
106
|
+
var import_js_format3 = require("@e22m4u/js-format");
|
|
107
|
+
function parseCookies(input) {
|
|
108
|
+
if (typeof input !== "string")
|
|
109
|
+
throw new import_js_format3.Errorf(
|
|
110
|
+
'The first parameter of "parseCookies" should be a String, but %v was given.',
|
|
111
|
+
input
|
|
112
|
+
);
|
|
113
|
+
return input.split(";").filter((v) => v !== "").map((v) => v.split("=")).reduce((cookies, tuple) => {
|
|
114
|
+
const key = decodeURIComponent(tuple[0]).trim();
|
|
115
|
+
const value = tuple[1] !== void 0 ? decodeURIComponent(tuple[1]).trim() : "";
|
|
116
|
+
cookies[key] = value;
|
|
117
|
+
return cookies;
|
|
118
|
+
}, {});
|
|
119
|
+
}
|
|
120
|
+
__name(parseCookies, "parseCookies");
|
|
121
|
+
|
|
121
122
|
// src/utils/to-camel-case.js
|
|
122
123
|
var import_js_format4 = require("@e22m4u/js-format");
|
|
123
124
|
function toCamelCase(input) {
|
|
124
125
|
if (typeof input !== "string")
|
|
125
126
|
throw new import_js_format4.Errorf(
|
|
126
|
-
'The first argument of "toCamelCase" should be a String, but %v given.',
|
|
127
|
+
'The first argument of "toCamelCase" should be a String, but %v was given.',
|
|
127
128
|
input
|
|
128
129
|
);
|
|
129
130
|
return input.replace(/(^\w|[A-Z]|\b\w)/g, (c) => c.toUpperCase()).replace(/\W+/g, "").replace(/(^\w)/g, (c) => c.toLowerCase());
|
|
@@ -136,13 +137,13 @@ var import_js_format5 = require("@e22m4u/js-format");
|
|
|
136
137
|
function createDebugger(name) {
|
|
137
138
|
if (typeof name !== "string")
|
|
138
139
|
throw new import_js_format5.Errorf(
|
|
139
|
-
'The first argument of "createDebugger" should be a String, but %v given.',
|
|
140
|
+
'The first argument of "createDebugger" should be a String, but %v was given.',
|
|
140
141
|
name
|
|
141
142
|
);
|
|
142
|
-
const
|
|
143
|
+
const debug = (0, import_debug.default)(`jsTrieRouter:${name}`);
|
|
143
144
|
return function(message, ...args) {
|
|
144
145
|
const interpolatedMessage = (0, import_js_format5.format)(message, ...args);
|
|
145
|
-
return
|
|
146
|
+
return debug(interpolatedMessage);
|
|
146
147
|
};
|
|
147
148
|
}
|
|
148
149
|
__name(createDebugger, "createDebugger");
|
|
@@ -152,7 +153,7 @@ var import_js_format6 = require("@e22m4u/js-format");
|
|
|
152
153
|
function isResponseSent(res) {
|
|
153
154
|
if (!res || typeof res !== "object" || Array.isArray(res) || typeof res.headersSent !== "boolean") {
|
|
154
155
|
throw new import_js_format6.Errorf(
|
|
155
|
-
'The first argument of "isResponseSent" should be an instance of ServerResponse, but %v given.',
|
|
156
|
+
'The first argument of "isResponseSent" should be an instance of ServerResponse, but %v was given.',
|
|
156
157
|
res
|
|
157
158
|
);
|
|
158
159
|
}
|
|
@@ -172,7 +173,7 @@ var import_js_format7 = require("@e22m4u/js-format");
|
|
|
172
173
|
function parseContentType(input) {
|
|
173
174
|
if (typeof input !== "string")
|
|
174
175
|
throw new import_js_format7.Errorf(
|
|
175
|
-
'The parameter "input" of "parseContentType" should be a String, but %v given.',
|
|
176
|
+
'The parameter "input" of "parseContentType" should be a String, but %v was given.',
|
|
176
177
|
input
|
|
177
178
|
);
|
|
178
179
|
const res = { mediaType: void 0, charset: void 0, boundary: void 0 };
|
|
@@ -196,9 +197,9 @@ __name(isWritableStream, "isWritableStream");
|
|
|
196
197
|
|
|
197
198
|
// src/utils/fetch-request-body.js
|
|
198
199
|
var import_http_errors = __toESM(require("http-errors"), 1);
|
|
199
|
-
var import_js_format8 = require("@e22m4u/js-format");
|
|
200
200
|
var import_http = require("http");
|
|
201
|
-
var
|
|
201
|
+
var import_js_format8 = require("@e22m4u/js-format");
|
|
202
|
+
var CHARACTER_ENCODING_LIST = [
|
|
202
203
|
"ascii",
|
|
203
204
|
"utf8",
|
|
204
205
|
"utf-8",
|
|
@@ -206,21 +207,17 @@ var BUFFER_ENCODING_LIST = [
|
|
|
206
207
|
"utf-16le",
|
|
207
208
|
"ucs2",
|
|
208
209
|
"ucs-2",
|
|
209
|
-
"
|
|
210
|
-
"base64url",
|
|
211
|
-
"latin1",
|
|
212
|
-
"binary",
|
|
213
|
-
"hex"
|
|
210
|
+
"latin1"
|
|
214
211
|
];
|
|
215
212
|
function fetchRequestBody(req, bodyBytesLimit = 0) {
|
|
216
213
|
if (!(req instanceof import_http.IncomingMessage))
|
|
217
214
|
throw new import_js_format8.Errorf(
|
|
218
|
-
'The first parameter of "fetchRequestBody" should be an IncomingMessage instance, but %v given.',
|
|
215
|
+
'The first parameter of "fetchRequestBody" should be an IncomingMessage instance, but %v was given.',
|
|
219
216
|
req
|
|
220
217
|
);
|
|
221
218
|
if (typeof bodyBytesLimit !== "number")
|
|
222
219
|
throw new import_js_format8.Errorf(
|
|
223
|
-
'The parameter "bodyBytesLimit" of "fetchRequestBody" should be a number, but %v given.',
|
|
220
|
+
'The parameter "bodyBytesLimit" of "fetchRequestBody" should be a number, but %v was given.',
|
|
224
221
|
bodyBytesLimit
|
|
225
222
|
);
|
|
226
223
|
return new Promise((resolve, reject) => {
|
|
@@ -238,7 +235,7 @@ function fetchRequestBody(req, bodyBytesLimit = 0) {
|
|
|
238
235
|
const parsedContentType = parseContentType(contentType);
|
|
239
236
|
if (parsedContentType && parsedContentType.charset) {
|
|
240
237
|
encoding = parsedContentType.charset.toLowerCase();
|
|
241
|
-
if (!
|
|
238
|
+
if (!CHARACTER_ENCODING_LIST.includes(encoding))
|
|
242
239
|
throw createError(
|
|
243
240
|
import_http_errors.default.UnsupportedMediaType,
|
|
244
241
|
"Request encoding %v is not supported.",
|
|
@@ -274,7 +271,7 @@ function fetchRequestBody(req, bodyBytesLimit = 0) {
|
|
|
274
271
|
return;
|
|
275
272
|
}
|
|
276
273
|
const buffer = Buffer.concat(data);
|
|
277
|
-
const body =
|
|
274
|
+
const body = buffer.toString(encoding);
|
|
278
275
|
resolve(body || void 0);
|
|
279
276
|
}, "onEnd");
|
|
280
277
|
const onError = /* @__PURE__ */ __name((error) => {
|
|
@@ -296,12 +293,12 @@ var import_http2 = require("http");
|
|
|
296
293
|
var import_querystring = __toESM(require("querystring"), 1);
|
|
297
294
|
var import_js_format10 = require("@e22m4u/js-format");
|
|
298
295
|
|
|
299
|
-
// src/utils/create-
|
|
296
|
+
// src/utils/create-cookies-string.js
|
|
300
297
|
var import_js_format9 = require("@e22m4u/js-format");
|
|
301
|
-
function
|
|
298
|
+
function createCookiesString(data) {
|
|
302
299
|
if (!data || typeof data !== "object" || Array.isArray(data))
|
|
303
300
|
throw new import_js_format9.Errorf(
|
|
304
|
-
'The first parameter of "
|
|
301
|
+
'The first parameter of "createCookiesString" should be an Object, but %v was given.',
|
|
305
302
|
data
|
|
306
303
|
);
|
|
307
304
|
let cookies = "";
|
|
@@ -313,68 +310,71 @@ function createCookieString(data) {
|
|
|
313
310
|
}
|
|
314
311
|
return cookies.trim();
|
|
315
312
|
}
|
|
316
|
-
__name(
|
|
313
|
+
__name(createCookiesString, "createCookiesString");
|
|
317
314
|
|
|
318
315
|
// src/utils/create-request-mock.js
|
|
319
316
|
function createRequestMock(patch) {
|
|
320
317
|
if (patch != null && typeof patch !== "object" || Array.isArray(patch)) {
|
|
321
318
|
throw new import_js_format10.Errorf(
|
|
322
|
-
'The first parameter of "createRequestMock" should be an Object, but %v given.',
|
|
319
|
+
'The first parameter of "createRequestMock" should be an Object, but %v was given.',
|
|
323
320
|
patch
|
|
324
321
|
);
|
|
325
322
|
}
|
|
326
323
|
patch = patch || {};
|
|
327
324
|
if (patch.host != null && typeof patch.host !== "string")
|
|
328
325
|
throw new import_js_format10.Errorf(
|
|
329
|
-
'The parameter "host" of "createRequestMock" should be a String, but %v given.',
|
|
326
|
+
'The parameter "host" of "createRequestMock" should be a String, but %v was given.',
|
|
330
327
|
patch.host
|
|
331
328
|
);
|
|
332
329
|
if (patch.method != null && typeof patch.method !== "string")
|
|
333
330
|
throw new import_js_format10.Errorf(
|
|
334
|
-
'The parameter "method" of "createRequestMock" should be a String, but %v given.',
|
|
331
|
+
'The parameter "method" of "createRequestMock" should be a String, but %v was given.',
|
|
335
332
|
patch.method
|
|
336
333
|
);
|
|
337
334
|
if (patch.secure != null && typeof patch.secure !== "boolean")
|
|
338
335
|
throw new import_js_format10.Errorf(
|
|
339
|
-
'The parameter "secure" of "createRequestMock" should be a Boolean, but %v given.',
|
|
336
|
+
'The parameter "secure" of "createRequestMock" should be a Boolean, but %v was given.',
|
|
340
337
|
patch.secure
|
|
341
338
|
);
|
|
342
339
|
if (patch.path != null && typeof patch.path !== "string")
|
|
343
340
|
throw new import_js_format10.Errorf(
|
|
344
|
-
'The parameter "path" of "createRequestMock" should be a String, but %v given.',
|
|
341
|
+
'The parameter "path" of "createRequestMock" should be a String, but %v was given.',
|
|
345
342
|
patch.path
|
|
346
343
|
);
|
|
347
344
|
if (patch.query != null && typeof patch.query !== "object" && typeof patch.query !== "string" || Array.isArray(patch.query)) {
|
|
348
345
|
throw new import_js_format10.Errorf(
|
|
349
|
-
'The parameter "query" of "createRequestMock" should be a String or Object, but %v given.',
|
|
346
|
+
'The parameter "query" of "createRequestMock" should be a String or Object, but %v was given.',
|
|
350
347
|
patch.query
|
|
351
348
|
);
|
|
352
349
|
}
|
|
353
|
-
if (patch.
|
|
350
|
+
if (patch.cookies != null && typeof patch.cookies !== "string" && typeof patch.cookies !== "object" || Array.isArray(patch.cookies)) {
|
|
354
351
|
throw new import_js_format10.Errorf(
|
|
355
|
-
'The parameter "
|
|
356
|
-
patch.
|
|
352
|
+
'The parameter "cookies" of "createRequestMock" should be a String or Object, but %v was given.',
|
|
353
|
+
patch.cookies
|
|
357
354
|
);
|
|
358
355
|
}
|
|
359
356
|
if (patch.headers != null && typeof patch.headers !== "object" || Array.isArray(patch.headers)) {
|
|
360
357
|
throw new import_js_format10.Errorf(
|
|
361
|
-
'The parameter "headers" of "createRequestMock" should be an Object, but %v given.',
|
|
358
|
+
'The parameter "headers" of "createRequestMock" should be an Object, but %v was given.',
|
|
362
359
|
patch.headers
|
|
363
360
|
);
|
|
364
361
|
}
|
|
365
362
|
if (patch.stream != null && !isReadableStream(patch.stream))
|
|
366
363
|
throw new import_js_format10.Errorf(
|
|
367
|
-
'The parameter "stream" of "createRequestMock" should be a Stream, but %v given.',
|
|
364
|
+
'The parameter "stream" of "createRequestMock" should be a Stream, but %v was given.',
|
|
368
365
|
patch.stream
|
|
369
366
|
);
|
|
370
367
|
if (patch.encoding != null) {
|
|
371
368
|
if (typeof patch.encoding !== "string")
|
|
372
369
|
throw new import_js_format10.Errorf(
|
|
373
|
-
'The parameter "encoding" of "createRequestMock" should be a String, but %v given.',
|
|
370
|
+
'The parameter "encoding" of "createRequestMock" should be a String, but %v was given.',
|
|
371
|
+
patch.encoding
|
|
372
|
+
);
|
|
373
|
+
if (!CHARACTER_ENCODING_LIST.includes(patch.encoding))
|
|
374
|
+
throw new import_js_format10.Errorf(
|
|
375
|
+
"Character encoding %v is not supported.",
|
|
374
376
|
patch.encoding
|
|
375
377
|
);
|
|
376
|
-
if (!BUFFER_ENCODING_LIST.includes(patch.encoding))
|
|
377
|
-
throw new import_js_format10.Errorf("Buffer encoding %v is not supported.", patch.encoding);
|
|
378
378
|
}
|
|
379
379
|
if (patch.stream) {
|
|
380
380
|
if (patch.secure != null)
|
|
@@ -396,7 +396,7 @@ function createRequestMock(patch) {
|
|
|
396
396
|
patch.host,
|
|
397
397
|
patch.secure,
|
|
398
398
|
patch.body,
|
|
399
|
-
patch.
|
|
399
|
+
patch.cookies,
|
|
400
400
|
patch.encoding,
|
|
401
401
|
patch.headers
|
|
402
402
|
);
|
|
@@ -407,7 +407,7 @@ __name(createRequestMock, "createRequestMock");
|
|
|
407
407
|
function createRequestStream(secure, body, encoding) {
|
|
408
408
|
if (encoding != null && typeof encoding !== "string")
|
|
409
409
|
throw new import_js_format10.Errorf(
|
|
410
|
-
'The parameter "encoding" of "createRequestStream" should be a String, but %v given.',
|
|
410
|
+
'The parameter "encoding" of "createRequestStream" should be a String, but %v was given.',
|
|
411
411
|
encoding
|
|
412
412
|
);
|
|
413
413
|
encoding = encoding || "utf-8";
|
|
@@ -430,12 +430,12 @@ __name(createRequestStream, "createRequestStream");
|
|
|
430
430
|
function createRequestUrl(path, query) {
|
|
431
431
|
if (typeof path !== "string")
|
|
432
432
|
throw new import_js_format10.Errorf(
|
|
433
|
-
'The parameter "path" of "createRequestUrl" should be a String, but %v given.',
|
|
433
|
+
'The parameter "path" of "createRequestUrl" should be a String, but %v was given.',
|
|
434
434
|
path
|
|
435
435
|
);
|
|
436
436
|
if (query != null && typeof query !== "string" && typeof query !== "object" || Array.isArray(query)) {
|
|
437
437
|
throw new import_js_format10.Errorf(
|
|
438
|
-
'The parameter "query" of "createRequestUrl" should be a String or Object, but %v given.',
|
|
438
|
+
'The parameter "query" of "createRequestUrl" should be a String or Object, but %v was given.',
|
|
439
439
|
query
|
|
440
440
|
);
|
|
441
441
|
}
|
|
@@ -449,48 +449,49 @@ function createRequestUrl(path, query) {
|
|
|
449
449
|
return url;
|
|
450
450
|
}
|
|
451
451
|
__name(createRequestUrl, "createRequestUrl");
|
|
452
|
-
function createRequestHeaders(host, secure, body,
|
|
452
|
+
function createRequestHeaders(host, secure, body, cookies, encoding, headers) {
|
|
453
453
|
if (host != null && typeof host !== "string")
|
|
454
454
|
throw new import_js_format10.Errorf(
|
|
455
|
-
'The parameter "host" of "createRequestHeaders" a non-empty String, but %v given.',
|
|
455
|
+
'The parameter "host" of "createRequestHeaders" a non-empty String, but %v was given.',
|
|
456
456
|
host
|
|
457
457
|
);
|
|
458
458
|
host = host || "localhost";
|
|
459
459
|
if (secure != null && typeof secure !== "boolean")
|
|
460
460
|
throw new import_js_format10.Errorf(
|
|
461
|
-
'The parameter "secure" of "createRequestHeaders" should be a String, but %v given.',
|
|
461
|
+
'The parameter "secure" of "createRequestHeaders" should be a String, but %v was given.',
|
|
462
462
|
secure
|
|
463
463
|
);
|
|
464
464
|
secure = Boolean(secure);
|
|
465
|
-
if (
|
|
465
|
+
if (cookies != null && typeof cookies !== "object" && typeof cookies !== "string" || Array.isArray(cookies)) {
|
|
466
466
|
throw new import_js_format10.Errorf(
|
|
467
|
-
'The parameter "
|
|
468
|
-
|
|
467
|
+
'The parameter "cookies" of "createRequestHeaders" should be a String or Object, but %v was given.',
|
|
468
|
+
cookies
|
|
469
469
|
);
|
|
470
470
|
}
|
|
471
471
|
if (headers != null && typeof headers !== "object" || Array.isArray(headers)) {
|
|
472
472
|
throw new import_js_format10.Errorf(
|
|
473
|
-
'The parameter "headers" of "createRequestHeaders" should be an Object, but %v given.',
|
|
473
|
+
'The parameter "headers" of "createRequestHeaders" should be an Object, but %v was given.',
|
|
474
474
|
headers
|
|
475
475
|
);
|
|
476
476
|
}
|
|
477
477
|
headers = headers || {};
|
|
478
478
|
if (encoding != null && typeof encoding !== "string")
|
|
479
479
|
throw new import_js_format10.Errorf(
|
|
480
|
-
'The parameter "encoding" of "createRequestHeaders" should be a String, but %v given.',
|
|
480
|
+
'The parameter "encoding" of "createRequestHeaders" should be a String, but %v was given.',
|
|
481
481
|
encoding
|
|
482
482
|
);
|
|
483
483
|
encoding = encoding || "utf-8";
|
|
484
484
|
const obj = { ...headers };
|
|
485
485
|
obj["host"] = host;
|
|
486
486
|
if (secure) obj["x-forwarded-proto"] = "https";
|
|
487
|
-
if (
|
|
488
|
-
if (typeof
|
|
487
|
+
if (cookies != null) {
|
|
488
|
+
if (typeof cookies === "string") {
|
|
489
489
|
obj["cookie"] = obj["cookie"] ? obj["cookie"] : "";
|
|
490
|
-
obj["cookie"] += cookie;
|
|
491
|
-
} else if (typeof
|
|
490
|
+
obj["cookie"] += obj["cookie"] ? `; ${cookies}` : cookies;
|
|
491
|
+
} else if (typeof cookies === "object") {
|
|
492
492
|
obj["cookie"] = obj["cookie"] ? obj["cookie"] : "";
|
|
493
|
-
|
|
493
|
+
const newCookies = createCookiesString(cookies);
|
|
494
|
+
obj["cookie"] += obj["cookie"] ? `; ${newCookies}` : newCookies;
|
|
494
495
|
}
|
|
495
496
|
}
|
|
496
497
|
if (obj["content-type"] == null) {
|
|
@@ -624,7 +625,7 @@ var import_js_format11 = require("@e22m4u/js-format");
|
|
|
624
625
|
function getRequestPathname(req) {
|
|
625
626
|
if (!req || typeof req !== "object" || Array.isArray(req) || typeof req.url !== "string") {
|
|
626
627
|
throw new import_js_format11.Errorf(
|
|
627
|
-
'The first argument of "getRequestPathname" should be an instance of IncomingMessage, but %v given.',
|
|
628
|
+
'The first argument of "getRequestPathname" should be an instance of IncomingMessage, but %v was given.',
|
|
628
629
|
req
|
|
629
630
|
);
|
|
630
631
|
}
|
|
@@ -634,38 +635,11 @@ __name(getRequestPathname, "getRequestPathname");
|
|
|
634
635
|
|
|
635
636
|
// src/hooks/hook-registry.js
|
|
636
637
|
var import_js_format12 = require("@e22m4u/js-format");
|
|
637
|
-
|
|
638
|
-
// src/debuggable-service.js
|
|
639
|
-
var import_js_service = require("@e22m4u/js-service");
|
|
640
|
-
var import_js_service2 = require("@e22m4u/js-service");
|
|
641
|
-
var _DebuggableService = class _DebuggableService extends import_js_service.Service {
|
|
642
|
-
/**
|
|
643
|
-
* Debug.
|
|
644
|
-
*
|
|
645
|
-
* @type {Function}
|
|
646
|
-
*/
|
|
647
|
-
debug;
|
|
648
|
-
/**
|
|
649
|
-
* Constructor.
|
|
650
|
-
*
|
|
651
|
-
* @param {ServiceContainer} container
|
|
652
|
-
*/
|
|
653
|
-
constructor(container) {
|
|
654
|
-
super(container);
|
|
655
|
-
const serviceName = toCamelCase(this.constructor.name);
|
|
656
|
-
this.debug = createDebugger(serviceName);
|
|
657
|
-
this.debug("The %v is created.", this.constructor);
|
|
658
|
-
}
|
|
659
|
-
};
|
|
660
|
-
__name(_DebuggableService, "DebuggableService");
|
|
661
|
-
var DebuggableService = _DebuggableService;
|
|
662
|
-
|
|
663
|
-
// src/hooks/hook-registry.js
|
|
664
638
|
var HookType = {
|
|
665
639
|
PRE_HANDLER: "preHandler",
|
|
666
640
|
POST_HANDLER: "postHandler"
|
|
667
641
|
};
|
|
668
|
-
var _HookRegistry = class _HookRegistry
|
|
642
|
+
var _HookRegistry = class _HookRegistry {
|
|
669
643
|
/**
|
|
670
644
|
* Hooks.
|
|
671
645
|
*
|
|
@@ -682,12 +656,12 @@ var _HookRegistry = class _HookRegistry extends DebuggableService {
|
|
|
682
656
|
*/
|
|
683
657
|
addHook(type, hook) {
|
|
684
658
|
if (!type || typeof type !== "string")
|
|
685
|
-
throw new import_js_format12.Errorf("The hook type is required, but %v given.", type);
|
|
659
|
+
throw new import_js_format12.Errorf("The hook type is required, but %v was given.", type);
|
|
686
660
|
if (!Object.values(HookType).includes(type))
|
|
687
661
|
throw new import_js_format12.Errorf("The hook type %v is not supported.", type);
|
|
688
662
|
if (!hook || typeof hook !== "function")
|
|
689
663
|
throw new import_js_format12.Errorf(
|
|
690
|
-
"The hook %v should be a Function, but %v given.",
|
|
664
|
+
"The hook %v should be a Function, but %v was given.",
|
|
691
665
|
type,
|
|
692
666
|
hook
|
|
693
667
|
);
|
|
@@ -705,12 +679,12 @@ var _HookRegistry = class _HookRegistry extends DebuggableService {
|
|
|
705
679
|
*/
|
|
706
680
|
hasHook(type, hook) {
|
|
707
681
|
if (!type || typeof type !== "string")
|
|
708
|
-
throw new import_js_format12.Errorf("The hook type is required, but %v given.", type);
|
|
682
|
+
throw new import_js_format12.Errorf("The hook type is required, but %v was given.", type);
|
|
709
683
|
if (!Object.values(HookType).includes(type))
|
|
710
684
|
throw new import_js_format12.Errorf("The hook type %v is not supported.", type);
|
|
711
685
|
if (!hook || typeof hook !== "function")
|
|
712
686
|
throw new import_js_format12.Errorf(
|
|
713
|
-
"The hook %v should be a Function, but %v given.",
|
|
687
|
+
"The hook %v should be a Function, but %v was given.",
|
|
714
688
|
type,
|
|
715
689
|
hook
|
|
716
690
|
);
|
|
@@ -725,7 +699,7 @@ var _HookRegistry = class _HookRegistry extends DebuggableService {
|
|
|
725
699
|
*/
|
|
726
700
|
getHooks(type) {
|
|
727
701
|
if (!type || typeof type !== "string")
|
|
728
|
-
throw new import_js_format12.Errorf("The hook type is required, but %v given.", type);
|
|
702
|
+
throw new import_js_format12.Errorf("The hook type is required, but %v was given.", type);
|
|
729
703
|
if (!Object.values(HookType).includes(type))
|
|
730
704
|
throw new import_js_format12.Errorf("The hook type %v is not supported.", type);
|
|
731
705
|
return this._hooks.get(type) || [];
|
|
@@ -734,6 +708,25 @@ var _HookRegistry = class _HookRegistry extends DebuggableService {
|
|
|
734
708
|
__name(_HookRegistry, "HookRegistry");
|
|
735
709
|
var HookRegistry = _HookRegistry;
|
|
736
710
|
|
|
711
|
+
// src/debuggable-service.js
|
|
712
|
+
var import_js_service = require("@e22m4u/js-service");
|
|
713
|
+
var MODULE_DEBUG_NAMESPACE = "jsTrieRouter";
|
|
714
|
+
var _DebuggableService = class _DebuggableService extends import_js_service.DebuggableService {
|
|
715
|
+
/**
|
|
716
|
+
* Constructor.
|
|
717
|
+
*
|
|
718
|
+
* @param {ServiceContainer} container
|
|
719
|
+
*/
|
|
720
|
+
constructor(container = void 0) {
|
|
721
|
+
super(container, {
|
|
722
|
+
namespace: MODULE_DEBUG_NAMESPACE,
|
|
723
|
+
noEnvironmentNamespace: true
|
|
724
|
+
});
|
|
725
|
+
}
|
|
726
|
+
};
|
|
727
|
+
__name(_DebuggableService, "DebuggableService");
|
|
728
|
+
var DebuggableService = _DebuggableService;
|
|
729
|
+
|
|
737
730
|
// src/hooks/hook-invoker.js
|
|
738
731
|
var _HookInvoker = class _HookInvoker extends DebuggableService {
|
|
739
732
|
/**
|
|
@@ -748,19 +741,19 @@ var _HookInvoker = class _HookInvoker extends DebuggableService {
|
|
|
748
741
|
invokeAndContinueUntilValueReceived(route, hookType, response, ...args) {
|
|
749
742
|
if (!route || !(route instanceof Route))
|
|
750
743
|
throw new import_js_format13.Errorf(
|
|
751
|
-
'The parameter "route" of the HookInvoker.invokeAndContinueUntilValueReceived should be a Route instance, but %v given.',
|
|
744
|
+
'The parameter "route" of the HookInvoker.invokeAndContinueUntilValueReceived should be a Route instance, but %v was given.',
|
|
752
745
|
route
|
|
753
746
|
);
|
|
754
747
|
if (!hookType || typeof hookType !== "string")
|
|
755
748
|
throw new import_js_format13.Errorf(
|
|
756
|
-
'The parameter "hookType" of the HookInvoker.invokeAndContinueUntilValueReceived should be a non-empty String, but %v given.',
|
|
749
|
+
'The parameter "hookType" of the HookInvoker.invokeAndContinueUntilValueReceived should be a non-empty String, but %v was given.',
|
|
757
750
|
hookType
|
|
758
751
|
);
|
|
759
752
|
if (!Object.values(HookType).includes(hookType))
|
|
760
753
|
throw new import_js_format13.Errorf("The hook type %v is not supported.", hookType);
|
|
761
754
|
if (!response || typeof response !== "object" || Array.isArray(response) || typeof response.headersSent !== "boolean") {
|
|
762
755
|
throw new import_js_format13.Errorf(
|
|
763
|
-
'The parameter "response" of the HookInvoker.invokeAndContinueUntilValueReceived should be a ServerResponse instance, but %v given.',
|
|
756
|
+
'The parameter "response" of the HookInvoker.invokeAndContinueUntilValueReceived should be a ServerResponse instance, but %v was given.',
|
|
764
757
|
response
|
|
765
758
|
);
|
|
766
759
|
}
|
|
@@ -779,7 +772,6 @@ var _HookInvoker = class _HookInvoker extends DebuggableService {
|
|
|
779
772
|
} else if (isPromise(result)) {
|
|
780
773
|
result = result.then((prevVal) => {
|
|
781
774
|
if (isResponseSent(response)) {
|
|
782
|
-
result = response;
|
|
783
775
|
return;
|
|
784
776
|
}
|
|
785
777
|
if (prevVal != null) return prevVal;
|
|
@@ -796,6 +788,7 @@ __name(_HookInvoker, "HookInvoker");
|
|
|
796
788
|
var HookInvoker = _HookInvoker;
|
|
797
789
|
|
|
798
790
|
// src/route.js
|
|
791
|
+
var import_js_debug = require("@e22m4u/js-debug");
|
|
799
792
|
var HttpMethod = {
|
|
800
793
|
GET: "GET",
|
|
801
794
|
POST: "POST",
|
|
@@ -803,8 +796,7 @@ var HttpMethod = {
|
|
|
803
796
|
PATCH: "PATCH",
|
|
804
797
|
DELETE: "DELETE"
|
|
805
798
|
};
|
|
806
|
-
var
|
|
807
|
-
var _Route = class _Route {
|
|
799
|
+
var _Route = class _Route extends import_js_debug.Debuggable {
|
|
808
800
|
/**
|
|
809
801
|
* Method.
|
|
810
802
|
*
|
|
@@ -871,26 +863,31 @@ var _Route = class _Route {
|
|
|
871
863
|
* @param {RouteDefinition} routeDef
|
|
872
864
|
*/
|
|
873
865
|
constructor(routeDef) {
|
|
866
|
+
super({
|
|
867
|
+
namespace: MODULE_DEBUG_NAMESPACE,
|
|
868
|
+
noEnvironmentNamespace: true,
|
|
869
|
+
noInstantiationMessage: true
|
|
870
|
+
});
|
|
874
871
|
if (!routeDef || typeof routeDef !== "object" || Array.isArray(routeDef))
|
|
875
872
|
throw new import_js_format14.Errorf(
|
|
876
|
-
"The first parameter of Route.
|
|
873
|
+
"The first parameter of Route.constructor should be an Object, but %v was given.",
|
|
877
874
|
routeDef
|
|
878
875
|
);
|
|
879
876
|
if (!routeDef.method || typeof routeDef.method !== "string")
|
|
880
877
|
throw new import_js_format14.Errorf(
|
|
881
|
-
'The option "method" of the Route should be a non-empty String, but %v given.',
|
|
878
|
+
'The option "method" of the Route should be a non-empty String, but %v was given.',
|
|
882
879
|
routeDef.method
|
|
883
880
|
);
|
|
884
881
|
this._method = routeDef.method.toUpperCase();
|
|
885
882
|
if (typeof routeDef.path !== "string")
|
|
886
883
|
throw new import_js_format14.Errorf(
|
|
887
|
-
'The option "path" of the Route should be a String, but %v given.',
|
|
884
|
+
'The option "path" of the Route should be a String, but %v was given.',
|
|
888
885
|
routeDef.path
|
|
889
886
|
);
|
|
890
887
|
this._path = routeDef.path;
|
|
891
888
|
if (typeof routeDef.handler !== "function")
|
|
892
889
|
throw new import_js_format14.Errorf(
|
|
893
|
-
'The option "handler" of the Route should be a Function, but %v given.',
|
|
890
|
+
'The option "handler" of the Route should be a Function, but %v was given.',
|
|
894
891
|
routeDef.handler
|
|
895
892
|
);
|
|
896
893
|
this._handler = routeDef.handler;
|
|
@@ -906,6 +903,7 @@ var _Route = class _Route {
|
|
|
906
903
|
this._hookRegistry.addHook(HookType.POST_HANDLER, hook);
|
|
907
904
|
});
|
|
908
905
|
}
|
|
906
|
+
this.ctorDebug("A new route %s %v was created.", this._method, this._path);
|
|
909
907
|
}
|
|
910
908
|
/**
|
|
911
909
|
* Handle request.
|
|
@@ -914,6 +912,7 @@ var _Route = class _Route {
|
|
|
914
912
|
* @returns {*}
|
|
915
913
|
*/
|
|
916
914
|
handle(context) {
|
|
915
|
+
const debug = this.getDebuggerFor(this.handle);
|
|
917
916
|
const requestPath = getRequestPathname(context.req);
|
|
918
917
|
debug(
|
|
919
918
|
"Invoking the Route handler for the request %s %v.",
|
|
@@ -937,22 +936,23 @@ var _DataSender = class _DataSender extends DebuggableService {
|
|
|
937
936
|
* @returns {undefined}
|
|
938
937
|
*/
|
|
939
938
|
send(res, data) {
|
|
939
|
+
const debug = this.getDebuggerFor(this.send);
|
|
940
940
|
if (data === res || res.headersSent) {
|
|
941
|
-
|
|
942
|
-
"Response sending was skipped because its headers where sent already
|
|
941
|
+
debug(
|
|
942
|
+
"Response sending was skipped because its headers where sent already."
|
|
943
943
|
);
|
|
944
944
|
return;
|
|
945
945
|
}
|
|
946
946
|
if (data == null) {
|
|
947
947
|
res.statusCode = 204;
|
|
948
948
|
res.end();
|
|
949
|
-
|
|
949
|
+
debug("The empty response was sent.");
|
|
950
950
|
return;
|
|
951
951
|
}
|
|
952
952
|
if (isReadableStream(data)) {
|
|
953
953
|
res.setHeader("Content-Type", "application/octet-stream");
|
|
954
954
|
data.pipe(res);
|
|
955
|
-
|
|
955
|
+
debug("The stream response was sent.");
|
|
956
956
|
return;
|
|
957
957
|
}
|
|
958
958
|
let debugMsg;
|
|
@@ -976,7 +976,7 @@ var _DataSender = class _DataSender extends DebuggableService {
|
|
|
976
976
|
break;
|
|
977
977
|
}
|
|
978
978
|
res.end(data);
|
|
979
|
-
|
|
979
|
+
debug(debugMsg);
|
|
980
980
|
}
|
|
981
981
|
};
|
|
982
982
|
__name(_DataSender, "DataSender");
|
|
@@ -996,6 +996,7 @@ var _ErrorSender = class _ErrorSender extends DebuggableService {
|
|
|
996
996
|
* @returns {undefined}
|
|
997
997
|
*/
|
|
998
998
|
send(req, res, error) {
|
|
999
|
+
const debug = this.getDebuggerFor(this.send);
|
|
999
1000
|
let safeError = {};
|
|
1000
1001
|
if (error) {
|
|
1001
1002
|
if (typeof error === "object") {
|
|
@@ -1027,11 +1028,16 @@ var _ErrorSender = class _ErrorSender extends DebuggableService {
|
|
|
1027
1028
|
};
|
|
1028
1029
|
console.warn((0, import_util.inspect)(requestData, inspectOptions));
|
|
1029
1030
|
console.warn((0, import_util.inspect)(body, inspectOptions));
|
|
1031
|
+
if (error.stack) {
|
|
1032
|
+
console.log(error.stack);
|
|
1033
|
+
} else {
|
|
1034
|
+
console.error(error);
|
|
1035
|
+
}
|
|
1030
1036
|
res.statusCode = statusCode;
|
|
1031
1037
|
res.setHeader("content-type", "application/json; charset=utf-8");
|
|
1032
1038
|
res.end(JSON.stringify(body, null, 2), "utf-8");
|
|
1033
|
-
|
|
1034
|
-
"The %s error
|
|
1039
|
+
debug(
|
|
1040
|
+
"The %s error was sent for the request %s %v.",
|
|
1035
1041
|
statusCode,
|
|
1036
1042
|
req.method,
|
|
1037
1043
|
getRequestPathname(req)
|
|
@@ -1045,11 +1051,12 @@ var _ErrorSender = class _ErrorSender extends DebuggableService {
|
|
|
1045
1051
|
* @returns {undefined}
|
|
1046
1052
|
*/
|
|
1047
1053
|
send404(req, res) {
|
|
1054
|
+
const debug = this.getDebuggerFor(this.send404);
|
|
1048
1055
|
res.statusCode = 404;
|
|
1049
1056
|
res.setHeader("content-type", "text/plain; charset=utf-8");
|
|
1050
1057
|
res.end("404 Not Found", "utf-8");
|
|
1051
|
-
|
|
1052
|
-
"The 404 error
|
|
1058
|
+
debug(
|
|
1059
|
+
"The 404 error was sent for the request %s %v.",
|
|
1053
1060
|
req.method,
|
|
1054
1061
|
getRequestPathname(req)
|
|
1055
1062
|
);
|
|
@@ -1090,7 +1097,7 @@ var _RouterOptions = class _RouterOptions extends DebuggableService {
|
|
|
1090
1097
|
setRequestBodyBytesLimit(input) {
|
|
1091
1098
|
if (typeof input !== "number" || input < 0)
|
|
1092
1099
|
throw new import_js_format16.Errorf(
|
|
1093
|
-
'The option "requestBodyBytesLimit" must be a positive Number or 0, but %v given.',
|
|
1100
|
+
'The option "requestBodyBytesLimit" must be a positive Number or 0, but %v was given.',
|
|
1094
1101
|
input
|
|
1095
1102
|
);
|
|
1096
1103
|
this._requestBodyBytesLimit = input;
|
|
@@ -1123,12 +1130,12 @@ var _BodyParser = class _BodyParser extends DebuggableService {
|
|
|
1123
1130
|
defineParser(mediaType, parser) {
|
|
1124
1131
|
if (!mediaType || typeof mediaType !== "string")
|
|
1125
1132
|
throw new import_js_format17.Errorf(
|
|
1126
|
-
'The parameter "mediaType" of BodyParser.defineParser should be a non-empty String, but %v given.',
|
|
1133
|
+
'The parameter "mediaType" of BodyParser.defineParser should be a non-empty String, but %v was given.',
|
|
1127
1134
|
mediaType
|
|
1128
1135
|
);
|
|
1129
1136
|
if (!parser || typeof parser !== "function")
|
|
1130
1137
|
throw new import_js_format17.Errorf(
|
|
1131
|
-
'The parameter "parser" of BodyParser.defineParser should be a Function, but %v given.',
|
|
1138
|
+
'The parameter "parser" of BodyParser.defineParser should be a Function, but %v was given.',
|
|
1132
1139
|
parser
|
|
1133
1140
|
);
|
|
1134
1141
|
this._parsers[mediaType] = parser;
|
|
@@ -1143,7 +1150,7 @@ var _BodyParser = class _BodyParser extends DebuggableService {
|
|
|
1143
1150
|
hasParser(mediaType) {
|
|
1144
1151
|
if (!mediaType || typeof mediaType !== "string")
|
|
1145
1152
|
throw new import_js_format17.Errorf(
|
|
1146
|
-
'The parameter "mediaType" of BodyParser.hasParser should be a non-empty String, but %v given.',
|
|
1153
|
+
'The parameter "mediaType" of BodyParser.hasParser should be a non-empty String, but %v was given.',
|
|
1147
1154
|
mediaType
|
|
1148
1155
|
);
|
|
1149
1156
|
return Boolean(this._parsers[mediaType]);
|
|
@@ -1157,7 +1164,7 @@ var _BodyParser = class _BodyParser extends DebuggableService {
|
|
|
1157
1164
|
deleteParser(mediaType) {
|
|
1158
1165
|
if (!mediaType || typeof mediaType !== "string")
|
|
1159
1166
|
throw new import_js_format17.Errorf(
|
|
1160
|
-
'The parameter "mediaType" of BodyParser.deleteParser should be a non-empty String, but %v given.',
|
|
1167
|
+
'The parameter "mediaType" of BodyParser.deleteParser should be a non-empty String, but %v was given.',
|
|
1161
1168
|
mediaType
|
|
1162
1169
|
);
|
|
1163
1170
|
const parser = this._parsers[mediaType];
|
|
@@ -1172,8 +1179,9 @@ var _BodyParser = class _BodyParser extends DebuggableService {
|
|
|
1172
1179
|
* @returns {Promise<*>|undefined}
|
|
1173
1180
|
*/
|
|
1174
1181
|
parse(req) {
|
|
1182
|
+
const debug = this.getDebuggerFor(this.parse);
|
|
1175
1183
|
if (!METHODS_WITH_BODY.includes(req.method.toUpperCase())) {
|
|
1176
|
-
|
|
1184
|
+
debug(
|
|
1177
1185
|
"Body parsing was skipped for the %s request.",
|
|
1178
1186
|
req.method.toUpperCase()
|
|
1179
1187
|
);
|
|
@@ -1184,8 +1192,8 @@ var _BodyParser = class _BodyParser extends DebuggableService {
|
|
|
1184
1192
|
"$1"
|
|
1185
1193
|
);
|
|
1186
1194
|
if (!contentType) {
|
|
1187
|
-
|
|
1188
|
-
"Body parsing was skipped because the request
|
|
1195
|
+
debug(
|
|
1196
|
+
"Body parsing was skipped because the request had no content type."
|
|
1189
1197
|
);
|
|
1190
1198
|
return;
|
|
1191
1199
|
}
|
|
@@ -1198,7 +1206,7 @@ var _BodyParser = class _BodyParser extends DebuggableService {
|
|
|
1198
1206
|
const parser = this._parsers[mediaType];
|
|
1199
1207
|
if (!parser) {
|
|
1200
1208
|
if (UNPARSABLE_MEDIA_TYPES.includes(mediaType)) {
|
|
1201
|
-
|
|
1209
|
+
debug("Body parsing was skipped for %v.", mediaType);
|
|
1202
1210
|
return;
|
|
1203
1211
|
}
|
|
1204
1212
|
throw createError(
|
|
@@ -1221,9 +1229,7 @@ function parseJsonBody(input) {
|
|
|
1221
1229
|
try {
|
|
1222
1230
|
return JSON.parse(input);
|
|
1223
1231
|
} catch (error) {
|
|
1224
|
-
|
|
1225
|
-
console.warn(error);
|
|
1226
|
-
throw createError(import_http_errors2.default.BadRequest, "Unable to parse request body.");
|
|
1232
|
+
throw createError(import_http_errors2.default.BadRequest, error.message);
|
|
1227
1233
|
}
|
|
1228
1234
|
}
|
|
1229
1235
|
__name(parseJsonBody, "parseJsonBody");
|
|
@@ -1238,16 +1244,17 @@ var _QueryParser = class _QueryParser extends DebuggableService {
|
|
|
1238
1244
|
* @returns {object}
|
|
1239
1245
|
*/
|
|
1240
1246
|
parse(req) {
|
|
1247
|
+
const debug = this.getDebuggerFor(this.parse);
|
|
1241
1248
|
const queryStr = req.url.replace(/^[^?]*\??/, "");
|
|
1242
1249
|
const query = queryStr ? import_querystring2.default.parse(queryStr) : {};
|
|
1243
1250
|
const queryKeys = Object.keys(query);
|
|
1244
1251
|
if (queryKeys.length) {
|
|
1245
1252
|
queryKeys.forEach((key) => {
|
|
1246
|
-
|
|
1253
|
+
debug("The query parameter %v had the value %v.", key, query[key]);
|
|
1247
1254
|
});
|
|
1248
1255
|
} else {
|
|
1249
|
-
|
|
1250
|
-
"The request %s %v
|
|
1256
|
+
debug(
|
|
1257
|
+
"The request %s %v had no query parameters.",
|
|
1251
1258
|
req.method,
|
|
1252
1259
|
getRequestPathname(req)
|
|
1253
1260
|
);
|
|
@@ -1258,8 +1265,8 @@ var _QueryParser = class _QueryParser extends DebuggableService {
|
|
|
1258
1265
|
__name(_QueryParser, "QueryParser");
|
|
1259
1266
|
var QueryParser = _QueryParser;
|
|
1260
1267
|
|
|
1261
|
-
// src/parsers/
|
|
1262
|
-
var
|
|
1268
|
+
// src/parsers/cookies-parser.js
|
|
1269
|
+
var _CookiesParser = class _CookiesParser extends DebuggableService {
|
|
1263
1270
|
/**
|
|
1264
1271
|
* Parse
|
|
1265
1272
|
*
|
|
@@ -1267,25 +1274,26 @@ var _CookieParser = class _CookieParser extends DebuggableService {
|
|
|
1267
1274
|
* @returns {object}
|
|
1268
1275
|
*/
|
|
1269
1276
|
parse(req) {
|
|
1270
|
-
const
|
|
1271
|
-
const
|
|
1272
|
-
const
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1277
|
+
const debug = this.getDebuggerFor(this.parse);
|
|
1278
|
+
const cookiesString = req.headers["cookie"] || "";
|
|
1279
|
+
const cookies = parseCookies(cookiesString);
|
|
1280
|
+
const cookiesKeys = Object.keys(cookies);
|
|
1281
|
+
if (cookiesKeys.length) {
|
|
1282
|
+
cookiesKeys.forEach((key) => {
|
|
1283
|
+
debug("The cookie %v had the value %v.", key, cookies[key]);
|
|
1276
1284
|
});
|
|
1277
1285
|
} else {
|
|
1278
|
-
|
|
1279
|
-
"The request %s %v
|
|
1286
|
+
debug(
|
|
1287
|
+
"The request %s %v had no cookies.",
|
|
1280
1288
|
req.method,
|
|
1281
1289
|
getRequestPathname(req)
|
|
1282
1290
|
);
|
|
1283
1291
|
}
|
|
1284
|
-
return
|
|
1292
|
+
return cookies;
|
|
1285
1293
|
}
|
|
1286
1294
|
};
|
|
1287
|
-
__name(
|
|
1288
|
-
var
|
|
1295
|
+
__name(_CookiesParser, "CookiesParser");
|
|
1296
|
+
var CookiesParser = _CookiesParser;
|
|
1289
1297
|
|
|
1290
1298
|
// src/parsers/request-parser.js
|
|
1291
1299
|
var import_http3 = require("http");
|
|
@@ -1300,7 +1308,7 @@ var _RequestParser = class _RequestParser extends DebuggableService {
|
|
|
1300
1308
|
parse(req) {
|
|
1301
1309
|
if (!(req instanceof import_http3.IncomingMessage))
|
|
1302
1310
|
throw new import_js_format18.Errorf(
|
|
1303
|
-
"The first argument of RequestParser.parse should be an instance of IncomingMessage, but %v given.",
|
|
1311
|
+
"The first argument of RequestParser.parse should be an instance of IncomingMessage, but %v was given.",
|
|
1304
1312
|
req
|
|
1305
1313
|
);
|
|
1306
1314
|
const data = {};
|
|
@@ -1311,11 +1319,11 @@ var _RequestParser = class _RequestParser extends DebuggableService {
|
|
|
1311
1319
|
} else {
|
|
1312
1320
|
data.query = parsedQuery;
|
|
1313
1321
|
}
|
|
1314
|
-
const
|
|
1315
|
-
if (isPromise(
|
|
1316
|
-
promises.push(
|
|
1322
|
+
const parsedCookies = this.getService(CookiesParser).parse(req);
|
|
1323
|
+
if (isPromise(parsedCookies)) {
|
|
1324
|
+
promises.push(parsedCookies.then((v) => data.cookies = v));
|
|
1317
1325
|
} else {
|
|
1318
|
-
data.
|
|
1326
|
+
data.cookies = parsedCookies;
|
|
1319
1327
|
}
|
|
1320
1328
|
const parsedBody = this.getService(BodyParser).parse(req);
|
|
1321
1329
|
if (isPromise(parsedBody)) {
|
|
@@ -1323,7 +1331,7 @@ var _RequestParser = class _RequestParser extends DebuggableService {
|
|
|
1323
1331
|
} else {
|
|
1324
1332
|
data.body = parsedBody;
|
|
1325
1333
|
}
|
|
1326
|
-
data.headers =
|
|
1334
|
+
data.headers = Object.assign({}, req.headers);
|
|
1327
1335
|
return promises.length ? Promise.all(promises).then(() => data) : data;
|
|
1328
1336
|
}
|
|
1329
1337
|
};
|
|
@@ -1333,7 +1341,7 @@ var RequestParser = _RequestParser;
|
|
|
1333
1341
|
// src/route-registry.js
|
|
1334
1342
|
var import_js_format19 = require("@e22m4u/js-format");
|
|
1335
1343
|
var import_js_path_trie = require("@e22m4u/js-path-trie");
|
|
1336
|
-
var
|
|
1344
|
+
var import_js_service2 = require("@e22m4u/js-service");
|
|
1337
1345
|
var _RouteRegistry = class _RouteRegistry extends DebuggableService {
|
|
1338
1346
|
/**
|
|
1339
1347
|
* Constructor.
|
|
@@ -1351,16 +1359,17 @@ var _RouteRegistry = class _RouteRegistry extends DebuggableService {
|
|
|
1351
1359
|
* @returns {Route}
|
|
1352
1360
|
*/
|
|
1353
1361
|
defineRoute(routeDef) {
|
|
1362
|
+
const debug = this.getDebuggerFor(this.defineRoute);
|
|
1354
1363
|
if (!routeDef || typeof routeDef !== "object" || Array.isArray(routeDef))
|
|
1355
1364
|
throw new import_js_format19.Errorf(
|
|
1356
|
-
"The route definition should be an Object, but %v given.",
|
|
1365
|
+
"The route definition should be an Object, but %v was given.",
|
|
1357
1366
|
routeDef
|
|
1358
1367
|
);
|
|
1359
1368
|
const route = new Route(routeDef);
|
|
1360
1369
|
const triePath = `${route.method}/${route.path}`;
|
|
1361
1370
|
this._trie.add(triePath, route);
|
|
1362
|
-
|
|
1363
|
-
"The route %s %v
|
|
1371
|
+
debug(
|
|
1372
|
+
"The route %s %v was registered.",
|
|
1364
1373
|
route.method.toUpperCase(),
|
|
1365
1374
|
route.path
|
|
1366
1375
|
);
|
|
@@ -1373,9 +1382,10 @@ var _RouteRegistry = class _RouteRegistry extends DebuggableService {
|
|
|
1373
1382
|
* @returns {ResolvedRoute|undefined}
|
|
1374
1383
|
*/
|
|
1375
1384
|
matchRouteByRequest(req) {
|
|
1385
|
+
const debug = this.getDebuggerFor(this.matchRouteByRequest);
|
|
1376
1386
|
const requestPath = (req.url || "/").replace(/\?.*$/, "");
|
|
1377
|
-
|
|
1378
|
-
"Matching %s %v
|
|
1387
|
+
debug(
|
|
1388
|
+
"Matching routes with the request %s %v.",
|
|
1379
1389
|
req.method.toUpperCase(),
|
|
1380
1390
|
requestPath
|
|
1381
1391
|
);
|
|
@@ -1383,28 +1393,26 @@ var _RouteRegistry = class _RouteRegistry extends DebuggableService {
|
|
|
1383
1393
|
const resolved = this._trie.match(triePath);
|
|
1384
1394
|
if (resolved) {
|
|
1385
1395
|
const route = resolved.value;
|
|
1386
|
-
|
|
1387
|
-
"The
|
|
1388
|
-
req.method.toUpperCase(),
|
|
1389
|
-
requestPath,
|
|
1396
|
+
debug(
|
|
1397
|
+
"The route %s %v was matched.",
|
|
1390
1398
|
route.method.toUpperCase(),
|
|
1391
1399
|
route.path
|
|
1392
1400
|
);
|
|
1393
1401
|
const paramNames = Object.keys(resolved.params);
|
|
1394
|
-
if (paramNames) {
|
|
1402
|
+
if (paramNames.length) {
|
|
1395
1403
|
paramNames.forEach((name) => {
|
|
1396
|
-
|
|
1397
|
-
"The path parameter %v
|
|
1404
|
+
debug(
|
|
1405
|
+
"The path parameter %v had the value %v.",
|
|
1398
1406
|
name,
|
|
1399
1407
|
resolved.params[name]
|
|
1400
1408
|
);
|
|
1401
1409
|
});
|
|
1402
1410
|
} else {
|
|
1403
|
-
|
|
1411
|
+
debug("No path parameters found.");
|
|
1404
1412
|
}
|
|
1405
1413
|
return { route, params: resolved.params };
|
|
1406
1414
|
}
|
|
1407
|
-
|
|
1415
|
+
debug(
|
|
1408
1416
|
"No matched route for the request %s %v.",
|
|
1409
1417
|
req.method.toUpperCase(),
|
|
1410
1418
|
requestPath
|
|
@@ -1416,8 +1424,8 @@ var RouteRegistry = _RouteRegistry;
|
|
|
1416
1424
|
|
|
1417
1425
|
// src/request-context.js
|
|
1418
1426
|
var import_js_format20 = require("@e22m4u/js-format");
|
|
1427
|
+
var import_js_service3 = require("@e22m4u/js-service");
|
|
1419
1428
|
var import_js_service4 = require("@e22m4u/js-service");
|
|
1420
|
-
var import_js_service5 = require("@e22m4u/js-service");
|
|
1421
1429
|
var _RequestContext = class _RequestContext {
|
|
1422
1430
|
/**
|
|
1423
1431
|
* Service container.
|
|
@@ -1456,11 +1464,11 @@ var _RequestContext = class _RequestContext {
|
|
|
1456
1464
|
*/
|
|
1457
1465
|
headers = {};
|
|
1458
1466
|
/**
|
|
1459
|
-
* Parsed
|
|
1467
|
+
* Parsed cookies.
|
|
1460
1468
|
*
|
|
1461
1469
|
* @type {object}
|
|
1462
1470
|
*/
|
|
1463
|
-
|
|
1471
|
+
cookies = {};
|
|
1464
1472
|
/**
|
|
1465
1473
|
* Parsed body.
|
|
1466
1474
|
*
|
|
@@ -1508,22 +1516,22 @@ var _RequestContext = class _RequestContext {
|
|
|
1508
1516
|
* @param {import('http').ServerResponse} response
|
|
1509
1517
|
*/
|
|
1510
1518
|
constructor(container, request, response) {
|
|
1511
|
-
if (!(0,
|
|
1519
|
+
if (!(0, import_js_service4.isServiceContainer)(container))
|
|
1512
1520
|
throw new import_js_format20.Errorf(
|
|
1513
|
-
'The parameter "container" of RequestContext.constructor should be an instance of ServiceContainer, but %v given.',
|
|
1521
|
+
'The parameter "container" of RequestContext.constructor should be an instance of ServiceContainer, but %v was given.',
|
|
1514
1522
|
container
|
|
1515
1523
|
);
|
|
1516
1524
|
this.container = container;
|
|
1517
1525
|
if (!request || typeof request !== "object" || Array.isArray(request) || !isReadableStream(request)) {
|
|
1518
1526
|
throw new import_js_format20.Errorf(
|
|
1519
|
-
'The parameter "request" of RequestContext.constructor should be an instance of IncomingMessage, but %v given.',
|
|
1527
|
+
'The parameter "request" of RequestContext.constructor should be an instance of IncomingMessage, but %v was given.',
|
|
1520
1528
|
request
|
|
1521
1529
|
);
|
|
1522
1530
|
}
|
|
1523
1531
|
this.req = request;
|
|
1524
1532
|
if (!response || typeof response !== "object" || Array.isArray(response) || !isWritableStream(response)) {
|
|
1525
1533
|
throw new import_js_format20.Errorf(
|
|
1526
|
-
'The parameter "response" of RequestContext.constructor should be an instance of ServerResponse, but %v given.',
|
|
1534
|
+
'The parameter "response" of RequestContext.constructor should be an instance of ServerResponse, but %v was given.',
|
|
1527
1535
|
response
|
|
1528
1536
|
);
|
|
1529
1537
|
}
|
|
@@ -1534,7 +1542,7 @@ __name(_RequestContext, "RequestContext");
|
|
|
1534
1542
|
var RequestContext = _RequestContext;
|
|
1535
1543
|
|
|
1536
1544
|
// src/trie-router.js
|
|
1537
|
-
var
|
|
1545
|
+
var import_js_service5 = require("@e22m4u/js-service");
|
|
1538
1546
|
var _TrieRouter = class _TrieRouter extends DebuggableService {
|
|
1539
1547
|
/**
|
|
1540
1548
|
* Define route.
|
|
@@ -1553,11 +1561,11 @@ var _TrieRouter = class _TrieRouter extends DebuggableService {
|
|
|
1553
1561
|
* ```
|
|
1554
1562
|
* const router = new TrieRouter();
|
|
1555
1563
|
* router.defineRoute({
|
|
1556
|
-
* method: HttpMethod.POST,
|
|
1564
|
+
* method: HttpMethod.POST, // Request method.
|
|
1557
1565
|
* path: '/users/:id', // The path template may have parameters.
|
|
1558
|
-
* preHandler(ctx) { ... }, // The "preHandler"
|
|
1566
|
+
* preHandler(ctx) { ... }, // The "preHandler" executes before a route handler.
|
|
1559
1567
|
* handler(ctx) { ... }, // Request handler function.
|
|
1560
|
-
* postHandler(ctx, data) { ... }, // The "postHandler"
|
|
1568
|
+
* postHandler(ctx, data) { ... }, // The "postHandler" executes after a route handler.
|
|
1561
1569
|
* });
|
|
1562
1570
|
* ```
|
|
1563
1571
|
*
|
|
@@ -1595,28 +1603,33 @@ var _TrieRouter = class _TrieRouter extends DebuggableService {
|
|
|
1595
1603
|
* @private
|
|
1596
1604
|
*/
|
|
1597
1605
|
async _handleRequest(req, res) {
|
|
1606
|
+
const debug = this.getDebuggerFor(this._handleRequest);
|
|
1598
1607
|
const requestPath = (req.url || "/").replace(/\?.*$/, "");
|
|
1599
|
-
|
|
1608
|
+
debug(
|
|
1609
|
+
"Preparing to handle an incoming request %s %v.",
|
|
1610
|
+
req.method,
|
|
1611
|
+
requestPath
|
|
1612
|
+
);
|
|
1600
1613
|
const resolved = this.getService(RouteRegistry).matchRouteByRequest(req);
|
|
1601
1614
|
if (!resolved) {
|
|
1602
|
-
|
|
1615
|
+
debug("No route for the request %s %v.", req.method, requestPath);
|
|
1603
1616
|
this.getService(ErrorSender).send404(req, res);
|
|
1604
1617
|
} else {
|
|
1605
1618
|
const { route, params } = resolved;
|
|
1606
|
-
const container = new
|
|
1619
|
+
const container = new import_js_service5.ServiceContainer(this.container);
|
|
1607
1620
|
const context = new RequestContext(container, req, res);
|
|
1608
1621
|
container.set(RequestContext, context);
|
|
1609
1622
|
context.params = params;
|
|
1610
|
-
|
|
1611
|
-
if (isPromise(reqDataOrPromise)) {
|
|
1612
|
-
const reqData = await reqDataOrPromise;
|
|
1613
|
-
Object.assign(context, reqData);
|
|
1614
|
-
} else {
|
|
1615
|
-
Object.assign(context, reqDataOrPromise);
|
|
1616
|
-
}
|
|
1617
|
-
let data, error;
|
|
1618
|
-
const hookInvoker = this.getService(HookInvoker);
|
|
1623
|
+
let data;
|
|
1619
1624
|
try {
|
|
1625
|
+
const reqDataOrPromise = this.getService(RequestParser).parse(req);
|
|
1626
|
+
if (isPromise(reqDataOrPromise)) {
|
|
1627
|
+
const reqData = await reqDataOrPromise;
|
|
1628
|
+
Object.assign(context, reqData);
|
|
1629
|
+
} else {
|
|
1630
|
+
Object.assign(context, reqDataOrPromise);
|
|
1631
|
+
}
|
|
1632
|
+
const hookInvoker = this.getService(HookInvoker);
|
|
1620
1633
|
data = hookInvoker.invokeAndContinueUntilValueReceived(
|
|
1621
1634
|
route,
|
|
1622
1635
|
HookType.PRE_HANDLER,
|
|
@@ -1624,7 +1637,7 @@ var _TrieRouter = class _TrieRouter extends DebuggableService {
|
|
|
1624
1637
|
context
|
|
1625
1638
|
);
|
|
1626
1639
|
if (isPromise(data)) data = await data;
|
|
1627
|
-
if (data == null) {
|
|
1640
|
+
if (!isResponseSent(res) && data == null) {
|
|
1628
1641
|
data = route.handle(context);
|
|
1629
1642
|
if (isPromise(data)) data = await data;
|
|
1630
1643
|
let postHandlerData = hookInvoker.invokeAndContinueUntilValueReceived(
|
|
@@ -1638,12 +1651,11 @@ var _TrieRouter = class _TrieRouter extends DebuggableService {
|
|
|
1638
1651
|
postHandlerData = await postHandlerData;
|
|
1639
1652
|
if (postHandlerData != null) data = postHandlerData;
|
|
1640
1653
|
}
|
|
1641
|
-
} catch (
|
|
1642
|
-
error = err;
|
|
1643
|
-
}
|
|
1644
|
-
if (error) {
|
|
1654
|
+
} catch (error) {
|
|
1645
1655
|
this.getService(ErrorSender).send(req, res, error);
|
|
1646
|
-
|
|
1656
|
+
return;
|
|
1657
|
+
}
|
|
1658
|
+
if (!isResponseSent(res)) {
|
|
1647
1659
|
this.getService(DataSender).send(res, data);
|
|
1648
1660
|
}
|
|
1649
1661
|
}
|
|
@@ -1685,9 +1697,9 @@ __name(_TrieRouter, "TrieRouter");
|
|
|
1685
1697
|
var TrieRouter = _TrieRouter;
|
|
1686
1698
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1687
1699
|
0 && (module.exports = {
|
|
1688
|
-
BUFFER_ENCODING_LIST,
|
|
1689
1700
|
BodyParser,
|
|
1690
|
-
|
|
1701
|
+
CHARACTER_ENCODING_LIST,
|
|
1702
|
+
CookiesParser,
|
|
1691
1703
|
DataSender,
|
|
1692
1704
|
EXPOSED_ERROR_PROPERTIES,
|
|
1693
1705
|
ErrorSender,
|
|
@@ -1704,7 +1716,7 @@ var TrieRouter = _TrieRouter;
|
|
|
1704
1716
|
RouterOptions,
|
|
1705
1717
|
TrieRouter,
|
|
1706
1718
|
UNPARSABLE_MEDIA_TYPES,
|
|
1707
|
-
|
|
1719
|
+
createCookiesString,
|
|
1708
1720
|
createDebugger,
|
|
1709
1721
|
createError,
|
|
1710
1722
|
createRequestMock,
|
|
@@ -1716,7 +1728,7 @@ var TrieRouter = _TrieRouter;
|
|
|
1716
1728
|
isResponseSent,
|
|
1717
1729
|
isWritableStream,
|
|
1718
1730
|
parseContentType,
|
|
1719
|
-
|
|
1731
|
+
parseCookies,
|
|
1720
1732
|
parseJsonBody,
|
|
1721
1733
|
toCamelCase
|
|
1722
1734
|
});
|