@e22m4u/js-trie-router 0.4.0 → 0.4.2
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/.mocharc.cjs +1 -0
- package/README.md +49 -36
- package/dist/cjs/index.cjs +216 -157
- package/mocha-setup.js +4 -0
- package/package.json +2 -2
- package/src/debuggable-service.spec.js +1 -1
- package/src/hooks/hook-invoker.spec.js +1 -1
- package/src/hooks/hook-registry.spec.js +1 -1
- package/src/parsers/body-parser.d.ts +2 -2
- package/src/parsers/body-parser.js +6 -6
- package/src/parsers/body-parser.spec.js +2 -2
- package/src/parsers/cookies-parser.d.ts +2 -2
- package/src/parsers/cookies-parser.js +5 -5
- package/src/parsers/cookies-parser.spec.js +1 -1
- package/src/parsers/query-parser.d.ts +2 -2
- package/src/parsers/query-parser.js +5 -5
- package/src/parsers/query-parser.spec.js +1 -1
- package/src/parsers/request-parser.d.ts +2 -2
- package/src/parsers/request-parser.js +8 -8
- package/src/parsers/request-parser.spec.js +1 -1
- package/src/request-context.d.ts +13 -9
- package/src/request-context.js +75 -18
- package/src/request-context.spec.js +46 -18
- package/src/route-registry.d.ts +2 -2
- package/src/route-registry.js +7 -7
- package/src/route-registry.spec.js +1 -1
- package/src/route.js +1 -1
- package/src/route.spec.js +2 -2
- package/src/router-options.spec.js +1 -1
- package/src/senders/data-sender.d.ts +2 -2
- package/src/senders/data-sender.js +11 -11
- package/src/senders/data-sender.spec.js +1 -1
- package/src/senders/error-sender.d.ts +11 -6
- package/src/senders/error-sender.js +19 -19
- package/src/senders/error-sender.spec.js +6 -3
- package/src/trie-router.js +20 -24
- package/src/trie-router.spec.js +37 -25
- package/src/utils/clone-deep.js +1 -1
- package/src/utils/clone-deep.spec.js +1 -1
- package/src/utils/create-cookies-string.spec.js +1 -1
- package/src/utils/create-debugger.spec.js +1 -1
- package/src/utils/create-error.spec.js +1 -1
- package/src/utils/create-request-mock.js +11 -11
- package/src/utils/create-request-mock.spec.js +1 -1
- package/src/utils/create-response-mock.d.ts +2 -1
- package/src/utils/create-response-mock.js +30 -30
- package/src/utils/create-response-mock.spec.js +1 -1
- package/src/utils/create-route-mock.d.ts +19 -0
- package/src/utils/create-route-mock.js +22 -0
- package/src/utils/create-route-mock.spec.js +28 -0
- package/src/utils/fetch-request-body.d.ts +2 -2
- package/src/utils/fetch-request-body.js +16 -13
- package/src/utils/fetch-request-body.spec.js +1 -1
- package/src/utils/get-request-pathname.d.ts +2 -2
- package/src/utils/get-request-pathname.js +8 -8
- package/src/utils/get-request-pathname.spec.js +1 -1
- package/src/utils/index.d.ts +1 -0
- package/src/utils/index.js +1 -0
- package/src/utils/is-promise.spec.js +1 -1
- package/src/utils/is-readable-stream.spec.js +1 -1
- package/src/utils/is-response-sent.d.ts +2 -2
- package/src/utils/is-response-sent.js +8 -8
- package/src/utils/is-response-sent.spec.js +1 -1
- package/src/utils/is-writable-stream.spec.js +1 -1
- package/src/utils/parse-content-type.spec.js +1 -1
- package/src/utils/parse-cookies.spec.js +1 -1
- package/src/utils/to-camel-case.spec.js +1 -1
- package/src/chai.js +0 -7
package/mocha-setup.js
ADDED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@e22m4u/js-trie-router",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.2",
|
|
4
4
|
"description": "HTTP маршрутизатор для Node.js на основе префиксного дерева",
|
|
5
5
|
"author": "Mikhail Evstropov <e22m4u@yandex.ru>",
|
|
6
6
|
"license": "MIT",
|
|
@@ -58,7 +58,7 @@
|
|
|
58
58
|
"eslint": "~9.39.1",
|
|
59
59
|
"eslint-config-prettier": "~10.1.8",
|
|
60
60
|
"eslint-plugin-chai-expect": "~3.1.0",
|
|
61
|
-
"eslint-plugin-jsdoc": "~61.2.
|
|
61
|
+
"eslint-plugin-jsdoc": "~61.2.1",
|
|
62
62
|
"eslint-plugin-mocha": "~11.2.0",
|
|
63
63
|
"globals": "~16.5.0",
|
|
64
64
|
"husky": "~9.1.7",
|
|
@@ -46,7 +46,7 @@ export declare class BodyParser extends DebuggableService {
|
|
|
46
46
|
/**
|
|
47
47
|
* Parse.
|
|
48
48
|
*
|
|
49
|
-
* @param
|
|
49
|
+
* @param request
|
|
50
50
|
*/
|
|
51
|
-
parse<T = unknown>(
|
|
51
|
+
parse<T = unknown>(request: IncomingMessage): ValueOrPromise<T>;
|
|
52
52
|
}
|
|
@@ -96,19 +96,19 @@ export class BodyParser extends DebuggableService {
|
|
|
96
96
|
/**
|
|
97
97
|
* Parse.
|
|
98
98
|
*
|
|
99
|
-
* @param {import('http').IncomingMessage}
|
|
99
|
+
* @param {import('http').IncomingMessage} request
|
|
100
100
|
* @returns {Promise<*>|undefined}
|
|
101
101
|
*/
|
|
102
|
-
parse(
|
|
102
|
+
parse(request) {
|
|
103
103
|
const debug = this.getDebuggerFor(this.parse);
|
|
104
|
-
if (!METHODS_WITH_BODY.includes(
|
|
104
|
+
if (!METHODS_WITH_BODY.includes(request.method.toUpperCase())) {
|
|
105
105
|
debug(
|
|
106
106
|
'Body parsing was skipped for the %s request.',
|
|
107
|
-
|
|
107
|
+
request.method.toUpperCase(),
|
|
108
108
|
);
|
|
109
109
|
return;
|
|
110
110
|
}
|
|
111
|
-
const contentType = (
|
|
111
|
+
const contentType = (request.headers['content-type'] || '').replace(
|
|
112
112
|
/^([^;]+);.*$/,
|
|
113
113
|
'$1',
|
|
114
114
|
);
|
|
@@ -137,7 +137,7 @@ export class BodyParser extends DebuggableService {
|
|
|
137
137
|
);
|
|
138
138
|
}
|
|
139
139
|
const bodyBytesLimit = this.getService(RouterOptions).requestBodyBytesLimit;
|
|
140
|
-
return fetchRequestBody(
|
|
140
|
+
return fetchRequestBody(request, bodyBytesLimit).then(rawBody => {
|
|
141
141
|
if (rawBody != null) return parser(rawBody);
|
|
142
142
|
return rawBody;
|
|
143
143
|
});
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {expect} from '
|
|
1
|
+
import {expect} from 'chai';
|
|
2
2
|
import HttpErrors from 'http-errors';
|
|
3
3
|
import {HttpMethod} from '../route.js';
|
|
4
4
|
import {format} from '@e22m4u/js-format';
|
|
@@ -104,7 +104,7 @@ describe('BodyParser', function () {
|
|
|
104
104
|
});
|
|
105
105
|
});
|
|
106
106
|
|
|
107
|
-
describe('
|
|
107
|
+
describe('deleteParser', function () {
|
|
108
108
|
it('requires the parameter "mediaType" to be a non-empty String', function () {
|
|
109
109
|
const parser = new BodyParser();
|
|
110
110
|
const throwable = v => () => parser.deleteParser(v);
|
|
@@ -9,12 +9,12 @@ export class CookiesParser extends DebuggableService {
|
|
|
9
9
|
/**
|
|
10
10
|
* Parse
|
|
11
11
|
*
|
|
12
|
-
* @param {import('http').IncomingMessage}
|
|
12
|
+
* @param {import('http').IncomingMessage} request
|
|
13
13
|
* @returns {object}
|
|
14
14
|
*/
|
|
15
|
-
parse(
|
|
15
|
+
parse(request) {
|
|
16
16
|
const debug = this.getDebuggerFor(this.parse);
|
|
17
|
-
const cookiesString =
|
|
17
|
+
const cookiesString = request.headers['cookie'] || '';
|
|
18
18
|
const cookies = parseCookies(cookiesString);
|
|
19
19
|
const cookiesKeys = Object.keys(cookies);
|
|
20
20
|
if (cookiesKeys.length) {
|
|
@@ -24,8 +24,8 @@ export class CookiesParser extends DebuggableService {
|
|
|
24
24
|
} else {
|
|
25
25
|
debug(
|
|
26
26
|
'The request %s %v had no cookies.',
|
|
27
|
-
|
|
28
|
-
getRequestPathname(
|
|
27
|
+
request.method,
|
|
28
|
+
getRequestPathname(request),
|
|
29
29
|
);
|
|
30
30
|
}
|
|
31
31
|
return cookies;
|
|
@@ -9,12 +9,12 @@ export class QueryParser extends DebuggableService {
|
|
|
9
9
|
/**
|
|
10
10
|
* Parse
|
|
11
11
|
*
|
|
12
|
-
* @param {import('http').IncomingMessage}
|
|
12
|
+
* @param {import('http').IncomingMessage} request
|
|
13
13
|
* @returns {object}
|
|
14
14
|
*/
|
|
15
|
-
parse(
|
|
15
|
+
parse(request) {
|
|
16
16
|
const debug = this.getDebuggerFor(this.parse);
|
|
17
|
-
const queryStr =
|
|
17
|
+
const queryStr = request.url.replace(/^[^?]*\??/, '');
|
|
18
18
|
const query = queryStr ? querystring.parse(queryStr) : {};
|
|
19
19
|
const queryKeys = Object.keys(query);
|
|
20
20
|
if (queryKeys.length) {
|
|
@@ -24,8 +24,8 @@ export class QueryParser extends DebuggableService {
|
|
|
24
24
|
} else {
|
|
25
25
|
debug(
|
|
26
26
|
'The request %s %v had no query parameters.',
|
|
27
|
-
|
|
28
|
-
getRequestPathname(
|
|
27
|
+
request.method,
|
|
28
|
+
getRequestPathname(request),
|
|
29
29
|
);
|
|
30
30
|
}
|
|
31
31
|
return query;
|
|
@@ -28,7 +28,7 @@ export declare class RequestParser extends DebuggableService {
|
|
|
28
28
|
/**
|
|
29
29
|
* Parse.
|
|
30
30
|
*
|
|
31
|
-
* @param
|
|
31
|
+
* @param request
|
|
32
32
|
*/
|
|
33
|
-
parse(
|
|
33
|
+
parse(request: IncomingMessage): ValueOrPromise<ParsedRequestData>;
|
|
34
34
|
}
|
|
@@ -13,15 +13,15 @@ export class RequestParser extends DebuggableService {
|
|
|
13
13
|
/**
|
|
14
14
|
* Parse.
|
|
15
15
|
*
|
|
16
|
-
* @param {IncomingMessage}
|
|
16
|
+
* @param {IncomingMessage} request
|
|
17
17
|
* @returns {Promise<object>|object}
|
|
18
18
|
*/
|
|
19
|
-
parse(
|
|
20
|
-
if (!(
|
|
19
|
+
parse(request) {
|
|
20
|
+
if (!(request instanceof IncomingMessage))
|
|
21
21
|
throw new Errorf(
|
|
22
22
|
'The first argument of RequestParser.parse should be ' +
|
|
23
23
|
'an instance of IncomingMessage, but %v was given.',
|
|
24
|
-
|
|
24
|
+
request,
|
|
25
25
|
);
|
|
26
26
|
const data = {};
|
|
27
27
|
const promises = [];
|
|
@@ -29,7 +29,7 @@ export class RequestParser extends DebuggableService {
|
|
|
29
29
|
// значения, так как парсер может вернуть
|
|
30
30
|
// Promise, и тогда придется разрывать
|
|
31
31
|
// "eventLoop" с помощью "await"
|
|
32
|
-
const parsedQuery = this.getService(QueryParser).parse(
|
|
32
|
+
const parsedQuery = this.getService(QueryParser).parse(request);
|
|
33
33
|
if (isPromise(parsedQuery)) {
|
|
34
34
|
promises.push(parsedQuery.then(v => (data.query = v)));
|
|
35
35
|
} else {
|
|
@@ -39,7 +39,7 @@ export class RequestParser extends DebuggableService {
|
|
|
39
39
|
// данные заголовка "cookie" с проверкой
|
|
40
40
|
// значения на Promise, и разрываем
|
|
41
41
|
// "eventLoop" при необходимости
|
|
42
|
-
const parsedCookies = this.getService(CookiesParser).parse(
|
|
42
|
+
const parsedCookies = this.getService(CookiesParser).parse(request);
|
|
43
43
|
if (isPromise(parsedCookies)) {
|
|
44
44
|
promises.push(parsedCookies.then(v => (data.cookies = v)));
|
|
45
45
|
} else {
|
|
@@ -48,7 +48,7 @@ export class RequestParser extends DebuggableService {
|
|
|
48
48
|
// аналогично предыдущей операции, разбираем
|
|
49
49
|
// тело запроса с проверкой результата
|
|
50
50
|
// на наличие Promise
|
|
51
|
-
const parsedBody = this.getService(BodyParser).parse(
|
|
51
|
+
const parsedBody = this.getService(BodyParser).parse(request);
|
|
52
52
|
if (isPromise(parsedBody)) {
|
|
53
53
|
promises.push(parsedBody.then(v => (data.body = v)));
|
|
54
54
|
} else {
|
|
@@ -56,7 +56,7 @@ export class RequestParser extends DebuggableService {
|
|
|
56
56
|
}
|
|
57
57
|
// что бы предотвратить модификацию
|
|
58
58
|
// заголовков, возвращаем их копию
|
|
59
|
-
data.headers = Object.assign({},
|
|
59
|
+
data.headers = Object.assign({}, request.headers);
|
|
60
60
|
// если имеются асинхронные операции, то результат
|
|
61
61
|
// будет обернут в Promise, в противном случае
|
|
62
62
|
// данные возвращаются сразу
|
package/src/request-context.d.ts
CHANGED
|
@@ -1,10 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {IncomingMessage} from 'http';
|
|
3
|
-
import {RouteMeta} from './route.js';
|
|
4
|
-
import {ParsedQuery} from './parsers/index.js';
|
|
1
|
+
import {Route, RouteMeta} from './route.js';
|
|
5
2
|
import {ParsedCookies} from './utils/index.js';
|
|
6
|
-
import {ParsedHeaders} from './parsers/index.js';
|
|
7
3
|
import {ServiceContainer} from '@e22m4u/js-service';
|
|
4
|
+
import {IncomingMessage, ServerResponse} from 'http';
|
|
5
|
+
import {ParsedQuery, ParsedHeaders} from './parsers/index.js';
|
|
8
6
|
|
|
9
7
|
/**
|
|
10
8
|
* Parsed params.
|
|
@@ -20,17 +18,22 @@ export declare class RequestContext {
|
|
|
20
18
|
/**
|
|
21
19
|
* Container.
|
|
22
20
|
*/
|
|
23
|
-
|
|
21
|
+
get container(): ServiceContainer;
|
|
24
22
|
|
|
25
23
|
/**
|
|
26
24
|
* Request.
|
|
27
25
|
*/
|
|
28
|
-
|
|
26
|
+
get request(): IncomingMessage;
|
|
29
27
|
|
|
30
28
|
/**
|
|
31
29
|
* Response.
|
|
32
30
|
*/
|
|
33
|
-
|
|
31
|
+
get response(): ServerResponse;
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Route.
|
|
35
|
+
*/
|
|
36
|
+
get route(): Route;
|
|
34
37
|
|
|
35
38
|
/**
|
|
36
39
|
* Query.
|
|
@@ -60,7 +63,7 @@ export declare class RequestContext {
|
|
|
60
63
|
/**
|
|
61
64
|
* Route meta.
|
|
62
65
|
*/
|
|
63
|
-
meta: RouteMeta;
|
|
66
|
+
get meta(): RouteMeta;
|
|
64
67
|
|
|
65
68
|
/**
|
|
66
69
|
* Method.
|
|
@@ -88,5 +91,6 @@ export declare class RequestContext {
|
|
|
88
91
|
container: ServiceContainer,
|
|
89
92
|
request: IncomingMessage,
|
|
90
93
|
response: ServerResponse,
|
|
94
|
+
route: Route,
|
|
91
95
|
);
|
|
92
96
|
}
|
package/src/request-context.js
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
|
+
import {Route} from './route.js';
|
|
1
2
|
import {Errorf} from '@e22m4u/js-format';
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
import {ServiceContainer, isServiceContainer} from '@e22m4u/js-service';
|
|
4
|
+
|
|
5
|
+
import {
|
|
6
|
+
isReadableStream,
|
|
7
|
+
isWritableStream,
|
|
8
|
+
getRequestPathname,
|
|
9
|
+
} from './utils/index.js';
|
|
7
10
|
|
|
8
11
|
/**
|
|
9
12
|
* Request context.
|
|
@@ -12,23 +15,66 @@ export class RequestContext {
|
|
|
12
15
|
/**
|
|
13
16
|
* Service container.
|
|
14
17
|
*
|
|
15
|
-
* @type {
|
|
18
|
+
* @type {ServiceContainer}
|
|
19
|
+
*/
|
|
20
|
+
_container;
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Getter of service container.
|
|
24
|
+
*
|
|
25
|
+
* @type {ServiceContainer}
|
|
16
26
|
*/
|
|
17
|
-
|
|
27
|
+
get container() {
|
|
28
|
+
return this._container;
|
|
29
|
+
}
|
|
18
30
|
|
|
19
31
|
/**
|
|
20
32
|
* Request.
|
|
21
33
|
*
|
|
22
34
|
* @type {import('http').IncomingMessage}
|
|
23
35
|
*/
|
|
24
|
-
|
|
36
|
+
_request;
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Getter of request.
|
|
40
|
+
*
|
|
41
|
+
* @type {import('http').IncomingMessage}
|
|
42
|
+
*/
|
|
43
|
+
get request() {
|
|
44
|
+
return this._request;
|
|
45
|
+
}
|
|
25
46
|
|
|
26
47
|
/**
|
|
27
48
|
* Response.
|
|
28
49
|
*
|
|
29
50
|
* @type {import('http').ServerResponse}
|
|
30
51
|
*/
|
|
31
|
-
|
|
52
|
+
_response;
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Getter of response.
|
|
56
|
+
*
|
|
57
|
+
* @type {import('http').ServerResponse}
|
|
58
|
+
*/
|
|
59
|
+
get response() {
|
|
60
|
+
return this._response;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Route
|
|
65
|
+
*
|
|
66
|
+
* @type {Route}
|
|
67
|
+
*/
|
|
68
|
+
_route;
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Getter of route.
|
|
72
|
+
*
|
|
73
|
+
* @type {Route}
|
|
74
|
+
*/
|
|
75
|
+
get route() {
|
|
76
|
+
return this._route;
|
|
77
|
+
}
|
|
32
78
|
|
|
33
79
|
/**
|
|
34
80
|
* Query.
|
|
@@ -68,9 +114,11 @@ export class RequestContext {
|
|
|
68
114
|
/**
|
|
69
115
|
* Route meta.
|
|
70
116
|
*
|
|
71
|
-
* @type {
|
|
117
|
+
* @type {import('./route.js').RouteMeta}
|
|
72
118
|
*/
|
|
73
|
-
meta
|
|
119
|
+
get meta() {
|
|
120
|
+
return this.route.meta;
|
|
121
|
+
}
|
|
74
122
|
|
|
75
123
|
/**
|
|
76
124
|
* Method.
|
|
@@ -78,7 +126,7 @@ export class RequestContext {
|
|
|
78
126
|
* @returns {string}
|
|
79
127
|
*/
|
|
80
128
|
get method() {
|
|
81
|
-
return this.
|
|
129
|
+
return this.request.method.toUpperCase();
|
|
82
130
|
}
|
|
83
131
|
|
|
84
132
|
/**
|
|
@@ -87,7 +135,7 @@ export class RequestContext {
|
|
|
87
135
|
* @returns {string}
|
|
88
136
|
*/
|
|
89
137
|
get path() {
|
|
90
|
-
return this.
|
|
138
|
+
return this.request.url;
|
|
91
139
|
}
|
|
92
140
|
|
|
93
141
|
/**
|
|
@@ -105,7 +153,7 @@ export class RequestContext {
|
|
|
105
153
|
*/
|
|
106
154
|
get pathname() {
|
|
107
155
|
if (this._pathname != null) return this._pathname;
|
|
108
|
-
this._pathname = getRequestPathname(this.
|
|
156
|
+
this._pathname = getRequestPathname(this.request);
|
|
109
157
|
return this._pathname;
|
|
110
158
|
}
|
|
111
159
|
|
|
@@ -115,15 +163,16 @@ export class RequestContext {
|
|
|
115
163
|
* @param {ServiceContainer} container
|
|
116
164
|
* @param {import('http').IncomingMessage} request
|
|
117
165
|
* @param {import('http').ServerResponse} response
|
|
166
|
+
* @param {Route} route
|
|
118
167
|
*/
|
|
119
|
-
constructor(container, request, response) {
|
|
168
|
+
constructor(container, request, response, route) {
|
|
120
169
|
if (!isServiceContainer(container))
|
|
121
170
|
throw new Errorf(
|
|
122
171
|
'The parameter "container" of RequestContext.constructor ' +
|
|
123
172
|
'should be an instance of ServiceContainer, but %v was given.',
|
|
124
173
|
container,
|
|
125
174
|
);
|
|
126
|
-
this.
|
|
175
|
+
this._container = container;
|
|
127
176
|
if (
|
|
128
177
|
!request ||
|
|
129
178
|
typeof request !== 'object' ||
|
|
@@ -136,7 +185,7 @@ export class RequestContext {
|
|
|
136
185
|
request,
|
|
137
186
|
);
|
|
138
187
|
}
|
|
139
|
-
this.
|
|
188
|
+
this._request = request;
|
|
140
189
|
if (
|
|
141
190
|
!response ||
|
|
142
191
|
typeof response !== 'object' ||
|
|
@@ -149,6 +198,14 @@ export class RequestContext {
|
|
|
149
198
|
response,
|
|
150
199
|
);
|
|
151
200
|
}
|
|
152
|
-
this.
|
|
201
|
+
this._response = response;
|
|
202
|
+
if (!(route instanceof Route)) {
|
|
203
|
+
throw new Errorf(
|
|
204
|
+
'The parameter "route" of RequestContext.constructor ' +
|
|
205
|
+
'should be an instance of Route, but %v was given.',
|
|
206
|
+
route,
|
|
207
|
+
);
|
|
208
|
+
}
|
|
209
|
+
this._route = route;
|
|
153
210
|
}
|
|
154
211
|
}
|
|
@@ -1,16 +1,21 @@
|
|
|
1
|
-
import {expect} from '
|
|
1
|
+
import {expect} from 'chai';
|
|
2
2
|
import {format} from '@e22m4u/js-format';
|
|
3
|
-
import {createRequestMock} from './utils/index.js';
|
|
4
3
|
import {RequestContext} from './request-context.js';
|
|
5
4
|
import {ServiceContainer} from '@e22m4u/js-service';
|
|
6
|
-
|
|
5
|
+
|
|
6
|
+
import {
|
|
7
|
+
createRouteMock,
|
|
8
|
+
createRequestMock,
|
|
9
|
+
createResponseMock,
|
|
10
|
+
} from './utils/index.js';
|
|
7
11
|
|
|
8
12
|
describe('RequestContext', function () {
|
|
9
13
|
describe('constructor', function () {
|
|
10
14
|
it('requires the parameter "container" to be the ServiceContainer', function () {
|
|
11
15
|
const req = createRequestMock();
|
|
12
16
|
const res = createResponseMock();
|
|
13
|
-
const
|
|
17
|
+
const route = createRouteMock();
|
|
18
|
+
const throwable = v => () => new RequestContext(v, req, res, route);
|
|
14
19
|
const error = v =>
|
|
15
20
|
format(
|
|
16
21
|
'The parameter "container" of RequestContext.constructor ' +
|
|
@@ -32,8 +37,9 @@ describe('RequestContext', function () {
|
|
|
32
37
|
|
|
33
38
|
it('requires the parameter "request" to be the ServiceContainer', function () {
|
|
34
39
|
const res = createResponseMock();
|
|
40
|
+
const route = createRouteMock();
|
|
35
41
|
const cont = new ServiceContainer();
|
|
36
|
-
const throwable = v => () => new RequestContext(cont, v, res);
|
|
42
|
+
const throwable = v => () => new RequestContext(cont, v, res, route);
|
|
37
43
|
const error = v =>
|
|
38
44
|
format(
|
|
39
45
|
'The parameter "request" of RequestContext.constructor ' +
|
|
@@ -55,8 +61,9 @@ describe('RequestContext', function () {
|
|
|
55
61
|
|
|
56
62
|
it('requires the parameter "response" to be the ServiceContainer', function () {
|
|
57
63
|
const req = createRequestMock();
|
|
64
|
+
const route = createRouteMock();
|
|
58
65
|
const cont = new ServiceContainer();
|
|
59
|
-
const throwable = v => () => new RequestContext(cont, req, v);
|
|
66
|
+
const throwable = v => () => new RequestContext(cont, req, v, route);
|
|
60
67
|
const error = v =>
|
|
61
68
|
format(
|
|
62
69
|
'The parameter "response" of RequestContext.constructor ' +
|
|
@@ -76,22 +83,39 @@ describe('RequestContext', function () {
|
|
|
76
83
|
throwable(createResponseMock())();
|
|
77
84
|
});
|
|
78
85
|
|
|
79
|
-
it('
|
|
86
|
+
it('requires the parameter "route" to be the Route', function () {
|
|
80
87
|
const req = createRequestMock();
|
|
81
88
|
const res = createResponseMock();
|
|
82
89
|
const cont = new ServiceContainer();
|
|
83
|
-
const
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
90
|
+
const throwable = v => () => new RequestContext(cont, req, res, v);
|
|
91
|
+
const error = v =>
|
|
92
|
+
format(
|
|
93
|
+
'The parameter "route" of RequestContext.constructor ' +
|
|
94
|
+
'should be an instance of Route, but %s was given.',
|
|
95
|
+
v,
|
|
96
|
+
);
|
|
97
|
+
expect(throwable('str')).to.throw(error('"str"'));
|
|
98
|
+
expect(throwable('')).to.throw(error('""'));
|
|
99
|
+
expect(throwable(10)).to.throw(error('10'));
|
|
100
|
+
expect(throwable(0)).to.throw(error('0'));
|
|
101
|
+
expect(throwable(true)).to.throw(error('true'));
|
|
102
|
+
expect(throwable(false)).to.throw(error('false'));
|
|
103
|
+
expect(throwable(null)).to.throw(error('null'));
|
|
104
|
+
expect(throwable({})).to.throw(error('Object'));
|
|
105
|
+
expect(throwable([])).to.throw(error('Array'));
|
|
106
|
+
expect(throwable(undefined)).to.throw(error('undefined'));
|
|
107
|
+
throwable(createRouteMock())();
|
|
87
108
|
});
|
|
88
109
|
|
|
89
|
-
it('sets
|
|
110
|
+
it('sets properties from given arguments', function () {
|
|
90
111
|
const req = createRequestMock();
|
|
91
112
|
const res = createResponseMock();
|
|
113
|
+
const route = createRouteMock();
|
|
92
114
|
const cont = new ServiceContainer();
|
|
93
|
-
const ctx = new RequestContext(cont, req, res);
|
|
94
|
-
expect(ctx.
|
|
115
|
+
const ctx = new RequestContext(cont, req, res, route);
|
|
116
|
+
expect(ctx.container).to.be.eq(cont);
|
|
117
|
+
expect(ctx.request).to.be.eq(req);
|
|
118
|
+
expect(ctx.response).to.be.eq(res);
|
|
95
119
|
});
|
|
96
120
|
});
|
|
97
121
|
|
|
@@ -99,8 +123,9 @@ describe('RequestContext', function () {
|
|
|
99
123
|
it('returns the method name in upper case', function () {
|
|
100
124
|
const req = createRequestMock({method: 'post'});
|
|
101
125
|
const res = createResponseMock();
|
|
126
|
+
const route = createRouteMock();
|
|
102
127
|
const cont = new ServiceContainer();
|
|
103
|
-
const ctx = new RequestContext(cont, req, res);
|
|
128
|
+
const ctx = new RequestContext(cont, req, res, route);
|
|
104
129
|
expect(ctx.method).to.be.eq('POST');
|
|
105
130
|
});
|
|
106
131
|
});
|
|
@@ -109,8 +134,9 @@ describe('RequestContext', function () {
|
|
|
109
134
|
it('returns the request pathname with the query string', function () {
|
|
110
135
|
const req = createRequestMock({path: '/pathname?foo=bar'});
|
|
111
136
|
const res = createResponseMock();
|
|
137
|
+
const route = createRouteMock();
|
|
112
138
|
const cont = new ServiceContainer();
|
|
113
|
-
const ctx = new RequestContext(cont, req, res);
|
|
139
|
+
const ctx = new RequestContext(cont, req, res, route);
|
|
114
140
|
expect(req.url).to.be.eq('/pathname?foo=bar');
|
|
115
141
|
expect(ctx.path).to.be.eq('/pathname?foo=bar');
|
|
116
142
|
});
|
|
@@ -120,8 +146,9 @@ describe('RequestContext', function () {
|
|
|
120
146
|
it('returns the request pathname without the query string', function () {
|
|
121
147
|
const req = createRequestMock({path: '/pathname?foo=bar'});
|
|
122
148
|
const res = createResponseMock();
|
|
149
|
+
const route = createRouteMock();
|
|
123
150
|
const cont = new ServiceContainer();
|
|
124
|
-
const ctx = new RequestContext(cont, req, res);
|
|
151
|
+
const ctx = new RequestContext(cont, req, res, route);
|
|
125
152
|
expect(req.url).to.be.eq('/pathname?foo=bar');
|
|
126
153
|
expect(ctx.pathname).to.be.eq('/pathname');
|
|
127
154
|
});
|
|
@@ -129,8 +156,9 @@ describe('RequestContext', function () {
|
|
|
129
156
|
it('sets the cache to the "_pathname" property and uses is for next accesses', function () {
|
|
130
157
|
const req = createRequestMock({path: '/pathname'});
|
|
131
158
|
const res = createResponseMock();
|
|
159
|
+
const route = createRouteMock();
|
|
132
160
|
const cont = new ServiceContainer();
|
|
133
|
-
const ctx = new RequestContext(cont, req, res);
|
|
161
|
+
const ctx = new RequestContext(cont, req, res, route);
|
|
134
162
|
expect(ctx._pathname).to.be.undefined;
|
|
135
163
|
expect(ctx.pathname).to.be.eq('/pathname');
|
|
136
164
|
expect(ctx._pathname).to.be.eq('/pathname');
|
package/src/route-registry.d.ts
CHANGED
|
@@ -33,7 +33,7 @@ export declare class RouteRegistry extends DebuggableService {
|
|
|
33
33
|
/**
|
|
34
34
|
* Match route by request.
|
|
35
35
|
*
|
|
36
|
-
* @param
|
|
36
|
+
* @param request
|
|
37
37
|
*/
|
|
38
|
-
matchRouteByRequest(
|
|
38
|
+
matchRouteByRequest(request: IncomingMessage): ResolvedRoute | undefined;
|
|
39
39
|
}
|