@e22m4u/js-trie-router 0.0.2 → 0.0.4
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-ru.md +240 -0
- package/README.md +107 -76
- package/examples/cookie-parsing-example.js +1 -1
- package/examples/params-parsing-example.js +1 -1
- package/examples/query-parsing-example.js +1 -1
- package/examples/uptime-example.js +1 -1
- package/package.json +20 -21
- package/src/parsers/body-parser.js +2 -2
- package/src/request-context.js +1 -1
- package/src/request-context.spec.js +3 -3
- package/src/route-registry.js +1 -1
- package/src/route.js +11 -11
- package/src/route.spec.js +3 -3
- package/src/trie-router.d.ts +4 -4
- package/src/trie-router.js +4 -4
- package/src/trie-router.spec.js +20 -20
package/README-ru.md
ADDED
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
## @e22m4u/js-trie-router
|
|
2
|
+
|
|
3
|
+
*[English](./README.md) | Русский*
|
|
4
|
+
|
|
5
|
+
HTTP роутер для Node.js на основе
|
|
6
|
+
[префиксного дерева](https://ru.wikipedia.org/wiki/Trie) (trie).
|
|
7
|
+
|
|
8
|
+
- Поддержка [path-to-regexp](https://github.com/pillarjs/path-to-regexp) синтаксиса.
|
|
9
|
+
- Автоматический парсинг JSON-тела запроса.
|
|
10
|
+
- Парсинг строки запроса и заголовка `cookie`.
|
|
11
|
+
- Поддержка `preHandler` и `postHandler` хуков.
|
|
12
|
+
- Позволяет использовать асинхронные обработчики.
|
|
13
|
+
|
|
14
|
+
## Установка
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
npm install @e22m4u/js-trie-router
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Для загрузки ES-модуля требуется установить `"type": "module"` в файле
|
|
21
|
+
`package.json`, или использовать `.mjs` расширение.
|
|
22
|
+
|
|
23
|
+
## Обзор
|
|
24
|
+
|
|
25
|
+
Базовый пример создания экземпляра роутера, объявления маршрута
|
|
26
|
+
и передачи слушателя запросов `http` серверу.
|
|
27
|
+
|
|
28
|
+
```js
|
|
29
|
+
import http from 'http';
|
|
30
|
+
import {TrieRouter} from '@e22m4u/js-trie-router';
|
|
31
|
+
|
|
32
|
+
const server = new http.Server(); // создание экземпляра HTTP сервера
|
|
33
|
+
const router = new TrieRouter(); // создание экземпляра роутера
|
|
34
|
+
|
|
35
|
+
router.defineRoute({
|
|
36
|
+
method: 'GET', // метод запроса "GET", "POST" и т.д.
|
|
37
|
+
path: '/', // шаблон пути, пример "/user/:id"
|
|
38
|
+
handler(ctx) { // обработчик маршрута
|
|
39
|
+
return 'Hello world!';
|
|
40
|
+
},
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
server.on('request', router.requestListener); // подключение роутера
|
|
44
|
+
server.listen(3000, 'localhost'); // прослушивание запросов
|
|
45
|
+
|
|
46
|
+
// Open in browser http://localhost:3000
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### Контекст запроса
|
|
50
|
+
|
|
51
|
+
Первый параметр обработчика маршрута принимает экземпляр класса
|
|
52
|
+
`RequestContext` с набором свойств, содержащих разобранные
|
|
53
|
+
данные входящего запроса.
|
|
54
|
+
|
|
55
|
+
- `container: ServiceContainer` экземпляр [сервис-контейнера](https://npmjs.com/package/@e22m4u/js-service)
|
|
56
|
+
- `req: IncomingMessage` нативный поток входящего запроса
|
|
57
|
+
- `res: ServerResponse` нативный поток ответа сервера
|
|
58
|
+
- `params: ParsedParams` объект ключ-значение с параметрами пути
|
|
59
|
+
- `query: ParsedQuery` объект ключ-значение с параметрами строки запроса
|
|
60
|
+
- `headers: ParsedHeaders` объект ключ-значение с заголовками запроса
|
|
61
|
+
- `cookie: ParsedCookie` объект ключ-значение разобранного заголовка `cookie`
|
|
62
|
+
- `method: string` метод запроса в верхнем регистре, например `GET`, `POST` и т.д.
|
|
63
|
+
- `path: string` путь включающий строку запроса, например `/myPath?foo=bar`
|
|
64
|
+
- `pathname: string` путь запроса, например `/myMath`
|
|
65
|
+
|
|
66
|
+
Пример доступа к контексту из обработчика маршрута.
|
|
67
|
+
|
|
68
|
+
```js
|
|
69
|
+
router.defineRoute({
|
|
70
|
+
method: 'GET',
|
|
71
|
+
path: '/users/:id',
|
|
72
|
+
handler(ctx) {
|
|
73
|
+
// GET /users/10?include=city
|
|
74
|
+
// Cookie: foo=bar; baz=qux;
|
|
75
|
+
console.log(ctx.req); // IncomingMessage
|
|
76
|
+
console.log(ctx.res); // ServerResponse
|
|
77
|
+
console.log(ctx.params); // {id: 10}
|
|
78
|
+
console.log(ctx.query); // {include: 'city'}
|
|
79
|
+
console.log(ctx.headers); // {cookie: 'foo=bar; baz=qux;'}
|
|
80
|
+
console.log(ctx.cookie); // {foo: 'bar', baz: 'qux'}
|
|
81
|
+
console.log(ctx.method); // "GET"
|
|
82
|
+
console.log(ctx.path); // "/users/10?include=city"
|
|
83
|
+
console.log(ctx.pathname); // "/users/10"
|
|
84
|
+
// ...
|
|
85
|
+
},
|
|
86
|
+
});
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### Отправка ответа
|
|
90
|
+
|
|
91
|
+
Возвращаемое значение обработчика маршрута используется в качестве ответа
|
|
92
|
+
сервера. Тип значения влияет на представление возвращаемых данных. Например,
|
|
93
|
+
если результатом будет являться тип `object`, то такое значение автоматически
|
|
94
|
+
сериализуется в JSON.
|
|
95
|
+
|
|
96
|
+
| value | content-type |
|
|
97
|
+
|-----------|--------------------------|
|
|
98
|
+
| `string` | text/plain |
|
|
99
|
+
| `number` | application/json |
|
|
100
|
+
| `boolean` | application/json |
|
|
101
|
+
| `object` | application/json |
|
|
102
|
+
| `Buffer` | application/octet-stream |
|
|
103
|
+
| `Stream` | application/octet-stream |
|
|
104
|
+
|
|
105
|
+
Пример возвращаемого значения обработчиком маршрута.
|
|
106
|
+
|
|
107
|
+
```js
|
|
108
|
+
router.defineRoute({ // регистрация маршрута
|
|
109
|
+
// ...
|
|
110
|
+
handler(ctx) { // обработчик входящего запроса
|
|
111
|
+
return {foo: 'bar'}; // ответ будет представлен в виде JSON
|
|
112
|
+
},
|
|
113
|
+
});
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
Контекст запроса `ctx` содержит нативный экземпляр класса `ServerResponse`
|
|
117
|
+
модуля `http`, который может быть использован для ручного управления ответом.
|
|
118
|
+
|
|
119
|
+
```js
|
|
120
|
+
router.defineRoute({
|
|
121
|
+
// ...
|
|
122
|
+
handler(ctx) {
|
|
123
|
+
res.statusCode = 404;
|
|
124
|
+
res.setHeader('content-type', 'text/plain; charset=utf-8');
|
|
125
|
+
res.end('404 Not Found', 'utf-8');
|
|
126
|
+
},
|
|
127
|
+
});
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
### Хуки маршрута
|
|
131
|
+
|
|
132
|
+
Определение маршрута методом `defineRoute` позволяет задать хуки
|
|
133
|
+
для отслеживания и перехвата входящего запроса и ответа
|
|
134
|
+
конкретного маршрута.
|
|
135
|
+
|
|
136
|
+
- `preHandler` выполняется перед вызовом обработчика
|
|
137
|
+
- `postHandler` выполняется после вызова обработчика
|
|
138
|
+
|
|
139
|
+
#### preHandler
|
|
140
|
+
|
|
141
|
+
Перед вызовом обработчика маршрута может потребоваться выполнение
|
|
142
|
+
таких операции как авторизация и проверка параметров запроса. Для
|
|
143
|
+
этого можно использовать хук `preHandler`.
|
|
144
|
+
|
|
145
|
+
```js
|
|
146
|
+
router.defineRoute({ // регистрация маршрута
|
|
147
|
+
// ...
|
|
148
|
+
preHandler(ctx) {
|
|
149
|
+
// перед обработчиком маршрута
|
|
150
|
+
console.log(`Incoming request ${ctx.method} ${ctx.path}`);
|
|
151
|
+
// > incoming request GET /myPath
|
|
152
|
+
},
|
|
153
|
+
handler(ctx) {
|
|
154
|
+
return 'Hello world!';
|
|
155
|
+
},
|
|
156
|
+
});
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
Если хук `preHandler` возвращает значение отличное от `undefined` и `null`,
|
|
160
|
+
то такое значение будет использовано в качестве ответа сервера, а вызов
|
|
161
|
+
обработчика маршрута будет пропущен.
|
|
162
|
+
|
|
163
|
+
```js
|
|
164
|
+
router.defineRoute({ // регистрация маршрута
|
|
165
|
+
// ...
|
|
166
|
+
preHandler(ctx) {
|
|
167
|
+
// возвращение ответа сервера
|
|
168
|
+
return 'Are you authorized?';
|
|
169
|
+
},
|
|
170
|
+
handler(ctx) {
|
|
171
|
+
// данный обработчик не будет вызван, так как
|
|
172
|
+
// хук "preHandler" уже отправил ответ
|
|
173
|
+
},
|
|
174
|
+
});
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
#### postHandler
|
|
178
|
+
|
|
179
|
+
Возвращаемое значение обработчика маршрута передается вторым аргументом
|
|
180
|
+
хука `postHandler`. По аналогии с `preHandler`, если возвращаемое
|
|
181
|
+
значение отличается от `undefined` и `null`, то такое значение будет
|
|
182
|
+
использовано в качестве ответа сервера. Это может быть полезно для
|
|
183
|
+
модификации возвращаемого ответа.
|
|
184
|
+
|
|
185
|
+
```js
|
|
186
|
+
router.defineRoute({
|
|
187
|
+
// ...
|
|
188
|
+
handler(ctx) {
|
|
189
|
+
return 'Hello world!';
|
|
190
|
+
},
|
|
191
|
+
postHandler(ctx, data) {
|
|
192
|
+
// после обработчика маршрута
|
|
193
|
+
return data.toUpperCase(); // HELLO WORLD!
|
|
194
|
+
},
|
|
195
|
+
});
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
### Глобальные хуки
|
|
199
|
+
|
|
200
|
+
Экземпляр роутера `TrieRouter` позволяет задать глобальные хуки, которые
|
|
201
|
+
имеют более высокий приоритет перед хуками маршрута, и вызываются
|
|
202
|
+
в первую очередь.
|
|
203
|
+
|
|
204
|
+
- `preHandler` выполняется перед вызовом обработчика каждого маршрута
|
|
205
|
+
- `postHandler` выполняется после вызова обработчика каждого маршрута
|
|
206
|
+
|
|
207
|
+
Добавить глобальные хуки можно методом `addHook` экземпляра роутера,
|
|
208
|
+
где первым параметром передается название хука, а вторым его функция.
|
|
209
|
+
|
|
210
|
+
```js
|
|
211
|
+
router.addHook('preHandler', (ctx) => {
|
|
212
|
+
// перед обработчиком маршрута
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
router.addHook('postHandler', (ctx, data) => {
|
|
216
|
+
// после обработчика маршрута
|
|
217
|
+
});
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
Аналогично хукам маршрута, если глобальный хук возвращает значение
|
|
221
|
+
отличное от `undefined` и `null`, то такое значение будет использовано
|
|
222
|
+
как ответ сервера.
|
|
223
|
+
|
|
224
|
+
## Отладка
|
|
225
|
+
|
|
226
|
+
Установка переменной `DEBUG` перед командой запуска включает вывод логов.
|
|
227
|
+
|
|
228
|
+
```bash
|
|
229
|
+
DEBUG=jsTrieRouter* npm run test
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
## Тестирование
|
|
233
|
+
|
|
234
|
+
```bash
|
|
235
|
+
npm run test
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
## Лицензия
|
|
239
|
+
|
|
240
|
+
MIT
|
package/README.md
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
## @e22m4u/js-trie-router
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
[Trie](https://en.wikipedia.org/wiki/Trie) for routing.
|
|
3
|
+
*English | [Русский](./README-ru.md)*
|
|
5
4
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
-
|
|
5
|
+
HTTP router for Node.js based on
|
|
6
|
+
a [prefix tree](https://en.wikipedia.org/wiki/Trie) (trie).
|
|
7
|
+
|
|
8
|
+
- Supports [path-to-regexp](https://github.com/pillarjs/path-to-regexp) syntax.
|
|
9
|
+
- Parses JSON request body automatically.
|
|
10
|
+
- Parses query string and `cookie` header.
|
|
10
11
|
- Supports `preHandler` and `postHandler` hooks.
|
|
11
|
-
-
|
|
12
|
+
- Supports asynchronous handlers.
|
|
12
13
|
|
|
13
14
|
## Installation
|
|
14
15
|
|
|
@@ -16,55 +17,57 @@ A pure ES-module of the Node.js HTTP router that uses the
|
|
|
16
17
|
npm install @e22m4u/js-trie-router
|
|
17
18
|
```
|
|
18
19
|
|
|
19
|
-
To load
|
|
20
|
-
or use the `.mjs` extension.
|
|
20
|
+
To load the ES-module, you need to set `"type": "module"`
|
|
21
|
+
in the `package.json` file, or use the `.mjs` extension.
|
|
21
22
|
|
|
22
23
|
## Overview
|
|
23
24
|
|
|
24
|
-
A basic
|
|
25
|
+
A basic example of creating a router instance, defining
|
|
26
|
+
a route and startup Node.js HTTP server.
|
|
25
27
|
|
|
26
28
|
```js
|
|
27
29
|
import http from 'http';
|
|
28
|
-
import {TrieRouter} from '
|
|
29
|
-
import {HTTP_METHOD} from '../src/route.js';
|
|
30
|
+
import {TrieRouter} from '@e22m4u/js-trie-router';
|
|
30
31
|
|
|
31
|
-
const server = new http.Server(); //
|
|
32
|
-
const router = new TrieRouter(); //
|
|
32
|
+
const server = new http.Server(); // Node.js HTTP server
|
|
33
|
+
const router = new TrieRouter(); // TrieRouter instance
|
|
33
34
|
|
|
34
|
-
router.defineRoute({
|
|
35
|
-
method:
|
|
36
|
-
path: '/', //
|
|
37
|
-
handler(ctx) { //
|
|
35
|
+
router.defineRoute({ // route definition
|
|
36
|
+
method: 'GET', // request method "GET", "POST", etc.
|
|
37
|
+
path: '/', // path template, example "/user/:id"
|
|
38
|
+
handler(ctx) { // route handler
|
|
38
39
|
return 'Hello world!';
|
|
39
40
|
},
|
|
40
41
|
});
|
|
41
42
|
|
|
42
|
-
server.on('request', router.
|
|
43
|
-
server.listen(3000, 'localhost');
|
|
43
|
+
server.on('request', router.requestListener); // inject request listener
|
|
44
|
+
server.listen(3000, 'localhost'); // listen for requests
|
|
44
45
|
|
|
45
46
|
// Open in browser http://localhost:3000
|
|
46
47
|
```
|
|
47
48
|
|
|
48
|
-
###
|
|
49
|
+
### Request context
|
|
49
50
|
|
|
50
|
-
The first parameter of a route handler is
|
|
51
|
+
The first parameter of a route handler is an instance
|
|
52
|
+
of the `RequestContext` class which has a properties
|
|
53
|
+
set with contents of a parsed incoming request.
|
|
51
54
|
|
|
52
|
-
- `container: ServiceContainer`
|
|
53
|
-
- `req: IncomingMessage`
|
|
54
|
-
- `res: ServerResponse`
|
|
55
|
-
- `params: ParsedParams`
|
|
56
|
-
- `query: ParsedQuery`
|
|
57
|
-
- `headers: ParsedHeaders`
|
|
58
|
-
- `cookie: ParsedCookie`
|
|
59
|
-
- `method: string`
|
|
60
|
-
- `path: string`
|
|
61
|
-
- `pathname: string`
|
|
55
|
+
- `container: ServiceContainer` instance of [service container](https://npmjs.com/package/@e22m4u/js-service)
|
|
56
|
+
- `req: IncomingMessage` native incoming request stream
|
|
57
|
+
- `res: ServerResponse` native server response stream
|
|
58
|
+
- `params: ParsedParams` key-value object with path parameters
|
|
59
|
+
- `query: ParsedQuery` key-value object with query string parameters
|
|
60
|
+
- `headers: ParsedHeaders` key-value object with request headers
|
|
61
|
+
- `cookie: ParsedCookie` key-value object of parsed `cookie` header
|
|
62
|
+
- `method: string` request method in uppercase, e.g. `GET`, `POST`, etc.
|
|
63
|
+
- `path: string` path including query string, e.g. `/myPath?foo=bar`
|
|
64
|
+
- `pathname: string` request path, e.g. `/myMath`
|
|
62
65
|
|
|
63
|
-
|
|
66
|
+
Example of accessing the context from a route handler.
|
|
64
67
|
|
|
65
68
|
```js
|
|
66
69
|
router.defineRoute({
|
|
67
|
-
method: '
|
|
70
|
+
method: 'GET',
|
|
68
71
|
path: '/users/:id',
|
|
69
72
|
handler(ctx) {
|
|
70
73
|
// GET /users/10?include=city
|
|
@@ -75,7 +78,7 @@ router.defineRoute({
|
|
|
75
78
|
console.log(ctx.query); // {include: 'city'}
|
|
76
79
|
console.log(ctx.headers); // {cookie: 'foo=bar; baz=qux;'}
|
|
77
80
|
console.log(ctx.cookie); // {foo: 'bar', baz: 'qux'}
|
|
78
|
-
console.log(ctx.method); // "
|
|
81
|
+
console.log(ctx.method); // "GET"
|
|
79
82
|
console.log(ctx.path); // "/users/10?include=city"
|
|
80
83
|
console.log(ctx.pathname); // "/users/10"
|
|
81
84
|
// ...
|
|
@@ -83,9 +86,12 @@ router.defineRoute({
|
|
|
83
86
|
});
|
|
84
87
|
```
|
|
85
88
|
|
|
86
|
-
###
|
|
89
|
+
### Response sending
|
|
87
90
|
|
|
88
|
-
Return
|
|
91
|
+
Return value of a route handler is used as response data.
|
|
92
|
+
Value type affects representation of a response data. For example,
|
|
93
|
+
if a response data is of type `object`, it will be automatically
|
|
94
|
+
serialized to JSON.
|
|
89
95
|
|
|
90
96
|
| value | content-type |
|
|
91
97
|
|-----------|--------------------------|
|
|
@@ -96,20 +102,20 @@ Return values of a route handler will be sent as described below.
|
|
|
96
102
|
| `Buffer` | application/octet-stream |
|
|
97
103
|
| `Stream` | application/octet-stream |
|
|
98
104
|
|
|
99
|
-
|
|
105
|
+
Example of sending data as JSON.
|
|
100
106
|
|
|
101
107
|
```js
|
|
102
|
-
router.defineRoute({
|
|
108
|
+
router.defineRoute({ // register a route
|
|
103
109
|
// ...
|
|
104
|
-
handler(ctx) {
|
|
105
|
-
//
|
|
106
|
-
return {foo: 'bar'};
|
|
110
|
+
handler(ctx) { // incoming request handler
|
|
111
|
+
return {foo: 'bar'}; // response will be encoded to JSON
|
|
107
112
|
},
|
|
108
113
|
});
|
|
109
114
|
```
|
|
110
115
|
|
|
111
|
-
|
|
112
|
-
|
|
116
|
+
The request context `ctx` contains a native instance
|
|
117
|
+
of the `ServerResponse` class from the `http` module,
|
|
118
|
+
which can be used for manual response management.
|
|
113
119
|
|
|
114
120
|
```js
|
|
115
121
|
router.defineRoute({
|
|
@@ -124,39 +130,67 @@ router.defineRoute({
|
|
|
124
130
|
|
|
125
131
|
### Route hooks
|
|
126
132
|
|
|
127
|
-
|
|
133
|
+
Defining a route with the `defineRoute` method allows
|
|
134
|
+
to set up hooks to monitor and intercept requests and
|
|
135
|
+
responses for a specific route.
|
|
136
|
+
|
|
137
|
+
- `preHandler` executes before a route handler
|
|
138
|
+
- `postHandler` executes after a route handler
|
|
128
139
|
|
|
129
|
-
|
|
130
|
-
- `postHandler` is executed after a route handler.
|
|
140
|
+
#### preHandler
|
|
131
141
|
|
|
132
|
-
|
|
133
|
-
|
|
142
|
+
Before calling a route handler, operations such as authorization
|
|
143
|
+
and request validation may be performed in the `preHandler`
|
|
144
|
+
hook.
|
|
134
145
|
|
|
135
146
|
```js
|
|
136
|
-
router.defineRoute({
|
|
147
|
+
router.defineRoute({ // register a route
|
|
137
148
|
// ...
|
|
138
149
|
preHandler(ctx) {
|
|
139
|
-
|
|
150
|
+
// before the route handler
|
|
151
|
+
console.log(`incoming request ${ctx.method} ${ctx.path}`);
|
|
152
|
+
// > incoming request GET /myPath
|
|
140
153
|
},
|
|
141
154
|
handler(ctx) {
|
|
142
|
-
// the request handler will be skipped because
|
|
143
|
-
// the "preHandler" hook returns a non-empty value
|
|
144
155
|
return 'Hello world!';
|
|
145
156
|
},
|
|
146
157
|
});
|
|
147
158
|
```
|
|
148
159
|
|
|
149
|
-
A
|
|
150
|
-
|
|
160
|
+
A route handler will not be called if `preHandler` hook
|
|
161
|
+
returns a value other than `undefined` and `null`, because
|
|
162
|
+
that value will be sent as response data.
|
|
163
|
+
|
|
164
|
+
```js
|
|
165
|
+
router.defineRoute({ // register a route
|
|
166
|
+
// ...
|
|
167
|
+
preHandler(ctx) {
|
|
168
|
+
// return the response data
|
|
169
|
+
return 'Are you authorized?';
|
|
170
|
+
},
|
|
171
|
+
handler(ctx) {
|
|
172
|
+
// this handler will not be called
|
|
173
|
+
// because the "preHandler" hook
|
|
174
|
+
// has already sent the data
|
|
175
|
+
},
|
|
176
|
+
});
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
#### postHandler
|
|
180
|
+
|
|
181
|
+
Return value of a route handler is passed to the second
|
|
182
|
+
parameter of `postHandler` hook. It may be useful to modify
|
|
183
|
+
the value before being sent.
|
|
151
184
|
|
|
152
185
|
```js
|
|
153
186
|
router.defineRoute({
|
|
154
187
|
// ...
|
|
155
188
|
handler(ctx) {
|
|
189
|
+
// return the response data
|
|
156
190
|
return 'Hello world!';
|
|
157
191
|
},
|
|
158
|
-
|
|
159
|
-
//
|
|
192
|
+
postHandler(ctx, data) {
|
|
193
|
+
// modify the response data before send
|
|
160
194
|
return data.toUpperCase(); // HELLO WORLD!
|
|
161
195
|
},
|
|
162
196
|
});
|
|
@@ -164,33 +198,37 @@ router.defineRoute({
|
|
|
164
198
|
|
|
165
199
|
### Global hooks
|
|
166
200
|
|
|
167
|
-
A `
|
|
201
|
+
A `TrieRouter` instance allows to set up global hooks
|
|
202
|
+
that have higher priority over route hooks and are
|
|
203
|
+
called first.
|
|
168
204
|
|
|
169
|
-
- `preHandler`
|
|
170
|
-
- `postHandler`
|
|
205
|
+
- `preHandler` executes before each route handler
|
|
206
|
+
- `postHandler` executes after each route handler
|
|
171
207
|
|
|
172
|
-
|
|
173
|
-
|
|
208
|
+
Global hooks can be added using the `addHook` method
|
|
209
|
+
of a router instance, where the first parameter
|
|
210
|
+
is the hook name and the second is a function.
|
|
174
211
|
|
|
175
212
|
```js
|
|
176
213
|
router.addHook('preHandler', (ctx) => {
|
|
177
|
-
//
|
|
214
|
+
// before a route handler
|
|
178
215
|
});
|
|
179
216
|
|
|
180
217
|
router.addHook('postHandler', (ctx, data) => {
|
|
181
|
-
//
|
|
218
|
+
// after a route handler
|
|
182
219
|
});
|
|
183
220
|
```
|
|
184
221
|
|
|
185
|
-
Similar to
|
|
186
|
-
`undefined`
|
|
222
|
+
Similar to route hooks, if a global hook returns
|
|
223
|
+
a value other than `undefined` and `null`, that
|
|
224
|
+
value will be sent as response data.
|
|
187
225
|
|
|
188
|
-
##
|
|
226
|
+
## Debugging
|
|
189
227
|
|
|
190
|
-
Set
|
|
228
|
+
Set the `DEBUG` variable to enable log output.
|
|
191
229
|
|
|
192
230
|
```bash
|
|
193
|
-
DEBUG=
|
|
231
|
+
DEBUG=jsTrieRouter* npm run test
|
|
194
232
|
```
|
|
195
233
|
|
|
196
234
|
## Testing
|
|
@@ -199,13 +237,6 @@ DEBUG=jsPathTrie* npm run test
|
|
|
199
237
|
npm run test
|
|
200
238
|
```
|
|
201
239
|
|
|
202
|
-
## Contribution
|
|
203
|
-
|
|
204
|
-
- Bug fixes.
|
|
205
|
-
- Grammar correction.
|
|
206
|
-
- Documentation improvements.
|
|
207
|
-
- Vulnerability fixes.
|
|
208
|
-
|
|
209
240
|
## License
|
|
210
241
|
|
|
211
242
|
MIT
|
|
@@ -15,7 +15,7 @@ router.defineRoute({
|
|
|
15
15
|
// создаем экземпляр HTTP сервера
|
|
16
16
|
// и подключаем обработчик запросов
|
|
17
17
|
const server = new http.Server();
|
|
18
|
-
server.on('request', router.
|
|
18
|
+
server.on('request', router.requestListener);
|
|
19
19
|
|
|
20
20
|
// слушаем входящие запросы
|
|
21
21
|
// на указанный адрес и порт
|
|
@@ -15,7 +15,7 @@ router.defineRoute({
|
|
|
15
15
|
// создаем экземпляр HTTP сервера
|
|
16
16
|
// и подключаем обработчик запросов
|
|
17
17
|
const server = new http.Server();
|
|
18
|
-
server.on('request', router.
|
|
18
|
+
server.on('request', router.requestListener);
|
|
19
19
|
|
|
20
20
|
// слушаем входящие запросы
|
|
21
21
|
// на указанный адрес и порт
|
|
@@ -15,7 +15,7 @@ router.defineRoute({
|
|
|
15
15
|
// создаем экземпляр HTTP сервера
|
|
16
16
|
// и подключаем обработчик запросов
|
|
17
17
|
const server = new http.Server();
|
|
18
|
-
server.on('request', router.
|
|
18
|
+
server.on('request', router.requestListener);
|
|
19
19
|
|
|
20
20
|
// слушаем входящие запросы
|
|
21
21
|
// на указанный адрес и порт
|
|
@@ -27,7 +27,7 @@ router.defineRoute({
|
|
|
27
27
|
// создаем экземпляр HTTP сервера
|
|
28
28
|
// и подключаем обработчик запросов
|
|
29
29
|
const server = new http.Server();
|
|
30
|
-
server.on('request', router.
|
|
30
|
+
server.on('request', router.requestListener);
|
|
31
31
|
|
|
32
32
|
// слушаем входящие запросы
|
|
33
33
|
// на указанный адрес и порт
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@e22m4u/js-trie-router",
|
|
3
|
-
"version": "0.0.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "0.0.4",
|
|
4
|
+
"description": "HTTP router for Node.js based on a prefix tree",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/index.js",
|
|
7
7
|
"scripts": {
|
|
@@ -26,32 +26,31 @@
|
|
|
26
26
|
"author": "e22m4u <e22m4u@yandex.ru>",
|
|
27
27
|
"license": "MIT",
|
|
28
28
|
"homepage": "https://github.com/e22m4u/js-trie-router",
|
|
29
|
+
"dependencies": {
|
|
30
|
+
"@e22m4u/js-format": "~0.1.0",
|
|
31
|
+
"@e22m4u/js-path-trie": "~0.0.2",
|
|
32
|
+
"@e22m4u/js-service": "~0.1.0",
|
|
33
|
+
"debug": "~4.3.7",
|
|
34
|
+
"http-errors": "~2.0.0",
|
|
35
|
+
"statuses": "~2.0.1"
|
|
36
|
+
},
|
|
29
37
|
"devDependencies": {
|
|
30
|
-
"@commitlint/cli": "~19.
|
|
31
|
-
"@commitlint/config-conventional": "~19.
|
|
32
|
-
"@eslint/js": "~9.
|
|
33
|
-
"@types/chai-as-promised": "
|
|
38
|
+
"@commitlint/cli": "~19.5.0",
|
|
39
|
+
"@commitlint/config-conventional": "~19.5.0",
|
|
40
|
+
"@eslint/js": "~9.12.0",
|
|
41
|
+
"@types/chai-as-promised": "~8.0.1",
|
|
34
42
|
"c8": "~10.1.2",
|
|
35
43
|
"chai": "~5.1.1",
|
|
36
|
-
"chai-as-promised": "
|
|
37
|
-
"eslint": "~9.
|
|
44
|
+
"chai-as-promised": "~8.0.0",
|
|
45
|
+
"eslint": "~9.12.0",
|
|
38
46
|
"eslint-config-prettier": "~9.1.0",
|
|
39
47
|
"eslint-plugin-chai-expect": "~3.1.0",
|
|
40
|
-
"eslint-plugin-jsdoc": "
|
|
48
|
+
"eslint-plugin-jsdoc": "~50.3.1",
|
|
41
49
|
"eslint-plugin-mocha": "~10.5.0",
|
|
42
|
-
"globals": "~15.
|
|
43
|
-
"husky": "~9.1.
|
|
50
|
+
"globals": "~15.10.0",
|
|
51
|
+
"husky": "~9.1.6",
|
|
44
52
|
"mocha": "~10.7.3",
|
|
45
53
|
"prettier": "~3.3.3",
|
|
46
|
-
"typescript": "~5.
|
|
47
|
-
},
|
|
48
|
-
"dependencies": {
|
|
49
|
-
"@e22m4u/js-format": "^0.1.0",
|
|
50
|
-
"@e22m4u/js-path-trie": "^0.0.1",
|
|
51
|
-
"@e22m4u/js-service": "^0.0.12",
|
|
52
|
-
"debug": "^4.3.6",
|
|
53
|
-
"http-errors": "^2.0.0",
|
|
54
|
-
"path-to-regexp": "^7.1.0",
|
|
55
|
-
"statuses": "^2.0.1"
|
|
54
|
+
"typescript": "~5.6.2"
|
|
56
55
|
}
|
|
57
56
|
}
|
|
@@ -11,7 +11,7 @@ import {parseContentType} from '../utils/parse-content-type.js';
|
|
|
11
11
|
*
|
|
12
12
|
* @type {string[]}
|
|
13
13
|
*/
|
|
14
|
-
export const METHODS_WITH_BODY = ['
|
|
14
|
+
export const METHODS_WITH_BODY = ['POST', 'PUT', 'PATCH', 'DELETE'];
|
|
15
15
|
|
|
16
16
|
/**
|
|
17
17
|
* Unparsable media types.
|
|
@@ -100,7 +100,7 @@ export class BodyParser extends Service {
|
|
|
100
100
|
* @returns {Promise<*>|undefined}
|
|
101
101
|
*/
|
|
102
102
|
parse(req) {
|
|
103
|
-
if (!METHODS_WITH_BODY.includes(req.method.
|
|
103
|
+
if (!METHODS_WITH_BODY.includes(req.method.toUpperCase())) {
|
|
104
104
|
this.debug(
|
|
105
105
|
'Body parsing was skipped for the %s request.',
|
|
106
106
|
req.method.toUpperCase(),
|
package/src/request-context.js
CHANGED
|
@@ -88,12 +88,12 @@ describe('RequestContext', function () {
|
|
|
88
88
|
});
|
|
89
89
|
|
|
90
90
|
describe('method', function () {
|
|
91
|
-
it('returns the method name in
|
|
92
|
-
const req = createRequestMock({method: '
|
|
91
|
+
it('returns the method name in upper case', function () {
|
|
92
|
+
const req = createRequestMock({method: 'post'});
|
|
93
93
|
const res = createResponseMock();
|
|
94
94
|
const cnt = new ServiceContainer();
|
|
95
95
|
const ctx = new RequestContext(cnt, req, res);
|
|
96
|
-
expect(ctx.method).to.be.eq('
|
|
96
|
+
expect(ctx.method).to.be.eq('POST');
|
|
97
97
|
});
|
|
98
98
|
});
|
|
99
99
|
|
package/src/route-registry.js
CHANGED
|
@@ -61,7 +61,7 @@ export class RouteRegistry extends Service {
|
|
|
61
61
|
req.method.toUpperCase(),
|
|
62
62
|
requestPath,
|
|
63
63
|
);
|
|
64
|
-
const triePath = `${req.method.
|
|
64
|
+
const triePath = `${req.method.toUpperCase()}/${requestPath}`;
|
|
65
65
|
const resolved = this._trie.match(triePath);
|
|
66
66
|
if (resolved) {
|
|
67
67
|
const route = resolved.value;
|
package/src/route.js
CHANGED
|
@@ -22,19 +22,19 @@ import {getRequestPathname} from './utils/index.js';
|
|
|
22
22
|
* Http method.
|
|
23
23
|
*
|
|
24
24
|
* @type {{
|
|
25
|
-
*
|
|
26
|
-
* POST: '
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
25
|
+
* GET: 'GET',
|
|
26
|
+
* POST: 'POST',
|
|
27
|
+
* PUT: 'PUT',
|
|
28
|
+
* PATCH: 'PATCH',
|
|
29
|
+
* DELETE: 'DELETE',
|
|
30
30
|
* }}
|
|
31
31
|
*/
|
|
32
32
|
export const HTTP_METHOD = {
|
|
33
|
-
GET: '
|
|
34
|
-
POST: '
|
|
35
|
-
PUT: '
|
|
36
|
-
PATCH: '
|
|
37
|
-
DELETE: '
|
|
33
|
+
GET: 'GET',
|
|
34
|
+
POST: 'POST',
|
|
35
|
+
PUT: 'PUT',
|
|
36
|
+
PATCH: 'PATCH',
|
|
37
|
+
DELETE: 'DELETE',
|
|
38
38
|
};
|
|
39
39
|
|
|
40
40
|
/**
|
|
@@ -134,7 +134,7 @@ export class Route {
|
|
|
134
134
|
'a non-empty String, but %v given.',
|
|
135
135
|
routeDef.method,
|
|
136
136
|
);
|
|
137
|
-
this._method = routeDef.method.
|
|
137
|
+
this._method = routeDef.method.toUpperCase();
|
|
138
138
|
if (typeof routeDef.path !== 'string')
|
|
139
139
|
throw new Errorf(
|
|
140
140
|
'The option "path" of the Route should be ' + 'a String, but %v given.',
|
package/src/route.spec.js
CHANGED
|
@@ -195,13 +195,13 @@ describe('Route', function () {
|
|
|
195
195
|
throwable2(() => undefined)();
|
|
196
196
|
});
|
|
197
197
|
|
|
198
|
-
it('sets the option "method" in
|
|
198
|
+
it('sets the option "method" in upper case to the "method" property', function () {
|
|
199
199
|
const route = new Route({
|
|
200
|
-
method: '
|
|
200
|
+
method: 'post',
|
|
201
201
|
path: '/',
|
|
202
202
|
handler: () => undefined,
|
|
203
203
|
});
|
|
204
|
-
expect(route.method).to.be.eq('
|
|
204
|
+
expect(route.method).to.be.eq('POST');
|
|
205
205
|
});
|
|
206
206
|
|
|
207
207
|
it('sets the option "path" to the "path" property', function () {
|
package/src/trie-router.d.ts
CHANGED
|
@@ -39,7 +39,7 @@ export declare class TrieRouter extends Service {
|
|
|
39
39
|
defineRoute(routeDef: RouteDefinition): Route;
|
|
40
40
|
|
|
41
41
|
/**
|
|
42
|
-
* Request
|
|
42
|
+
* Request listener.
|
|
43
43
|
*
|
|
44
44
|
* Example:
|
|
45
45
|
* ```
|
|
@@ -48,13 +48,13 @@ export declare class TrieRouter extends Service {
|
|
|
48
48
|
*
|
|
49
49
|
* const router = new TrieRouter();
|
|
50
50
|
* const server = new http.Server();
|
|
51
|
-
* server.on('request', router.
|
|
52
|
-
* server.listen(3000);
|
|
51
|
+
* server.on('request', router.requestListener); // Sets the request listener.
|
|
52
|
+
* server.listen(3000); // Starts listening for connections.
|
|
53
53
|
* ```
|
|
54
54
|
*
|
|
55
55
|
* @returns {Function}
|
|
56
56
|
*/
|
|
57
|
-
get
|
|
57
|
+
get requestListener(): RequestListener;
|
|
58
58
|
|
|
59
59
|
/**
|
|
60
60
|
* Add hook.
|
package/src/trie-router.js
CHANGED
|
@@ -47,7 +47,7 @@ export class TrieRouter extends Service {
|
|
|
47
47
|
}
|
|
48
48
|
|
|
49
49
|
/**
|
|
50
|
-
* Request
|
|
50
|
+
* Request listener.
|
|
51
51
|
*
|
|
52
52
|
* Example:
|
|
53
53
|
* ```
|
|
@@ -56,13 +56,13 @@ export class TrieRouter extends Service {
|
|
|
56
56
|
*
|
|
57
57
|
* const router = new TrieRouter();
|
|
58
58
|
* const server = new http.Server();
|
|
59
|
-
* server.on('request', router.
|
|
60
|
-
* server.listen(3000);
|
|
59
|
+
* server.on('request', router.requestListener); // Sets the request listener.
|
|
60
|
+
* server.listen(3000); // Starts listening for connections.
|
|
61
61
|
* ```
|
|
62
62
|
*
|
|
63
63
|
* @returns {Function}
|
|
64
64
|
*/
|
|
65
|
-
get
|
|
65
|
+
get requestListener() {
|
|
66
66
|
return this._handleRequest.bind(this);
|
|
67
67
|
}
|
|
68
68
|
|
package/src/trie-router.spec.js
CHANGED
|
@@ -25,10 +25,10 @@ describe('TrieRouter', function () {
|
|
|
25
25
|
});
|
|
26
26
|
});
|
|
27
27
|
|
|
28
|
-
describe('
|
|
28
|
+
describe('requestListener', function () {
|
|
29
29
|
it('to be a function', function () {
|
|
30
30
|
const router = new TrieRouter();
|
|
31
|
-
expect(typeof router.
|
|
31
|
+
expect(typeof router.requestListener).to.be.eq('function');
|
|
32
32
|
});
|
|
33
33
|
|
|
34
34
|
it('passes request context to the route handler', function (done) {
|
|
@@ -43,7 +43,7 @@ describe('TrieRouter', function () {
|
|
|
43
43
|
});
|
|
44
44
|
const req = createRequestMock({path: '/test'});
|
|
45
45
|
const res = createResponseMock();
|
|
46
|
-
router.
|
|
46
|
+
router.requestListener(req, res);
|
|
47
47
|
});
|
|
48
48
|
|
|
49
49
|
it('passes path parameters to the request context', function (done) {
|
|
@@ -58,7 +58,7 @@ describe('TrieRouter', function () {
|
|
|
58
58
|
});
|
|
59
59
|
const req = createRequestMock({path: '/foo-bar'});
|
|
60
60
|
const res = createResponseMock();
|
|
61
|
-
router.
|
|
61
|
+
router.requestListener(req, res);
|
|
62
62
|
});
|
|
63
63
|
|
|
64
64
|
it('passes query parameters to the request context', function (done) {
|
|
@@ -73,7 +73,7 @@ describe('TrieRouter', function () {
|
|
|
73
73
|
});
|
|
74
74
|
const req = createRequestMock({path: '?p1=foo&p2=bar'});
|
|
75
75
|
const res = createResponseMock();
|
|
76
|
-
router.
|
|
76
|
+
router.requestListener(req, res);
|
|
77
77
|
});
|
|
78
78
|
|
|
79
79
|
it('passes parsed cookie to the request context', function (done) {
|
|
@@ -88,7 +88,7 @@ describe('TrieRouter', function () {
|
|
|
88
88
|
});
|
|
89
89
|
const req = createRequestMock({headers: {cookie: 'p1=foo; p2=bar;'}});
|
|
90
90
|
const res = createResponseMock();
|
|
91
|
-
router.
|
|
91
|
+
router.requestListener(req, res);
|
|
92
92
|
});
|
|
93
93
|
|
|
94
94
|
it('passes plain text body to the request context', function (done) {
|
|
@@ -104,7 +104,7 @@ describe('TrieRouter', function () {
|
|
|
104
104
|
});
|
|
105
105
|
const req = createRequestMock({method: HTTP_METHOD.POST, body});
|
|
106
106
|
const res = createResponseMock();
|
|
107
|
-
router.
|
|
107
|
+
router.requestListener(req, res);
|
|
108
108
|
});
|
|
109
109
|
|
|
110
110
|
it('passes parsed JSON body to the request context', function (done) {
|
|
@@ -120,7 +120,7 @@ describe('TrieRouter', function () {
|
|
|
120
120
|
});
|
|
121
121
|
const req = createRequestMock({method: HTTP_METHOD.POST, body: data});
|
|
122
122
|
const res = createResponseMock();
|
|
123
|
-
router.
|
|
123
|
+
router.requestListener(req, res);
|
|
124
124
|
});
|
|
125
125
|
|
|
126
126
|
it('passes headers to the request context', function (done) {
|
|
@@ -138,7 +138,7 @@ describe('TrieRouter', function () {
|
|
|
138
138
|
});
|
|
139
139
|
const req = createRequestMock({headers: {foo: 'bar'}});
|
|
140
140
|
const res = createResponseMock();
|
|
141
|
-
router.
|
|
141
|
+
router.requestListener(req, res);
|
|
142
142
|
});
|
|
143
143
|
|
|
144
144
|
it('uses DataSender to send the response', function (done) {
|
|
@@ -158,7 +158,7 @@ describe('TrieRouter', function () {
|
|
|
158
158
|
done();
|
|
159
159
|
},
|
|
160
160
|
});
|
|
161
|
-
router.
|
|
161
|
+
router.requestListener(req, res);
|
|
162
162
|
});
|
|
163
163
|
|
|
164
164
|
it('uses ErrorSender to send the response', function (done) {
|
|
@@ -181,7 +181,7 @@ describe('TrieRouter', function () {
|
|
|
181
181
|
done();
|
|
182
182
|
},
|
|
183
183
|
});
|
|
184
|
-
router.
|
|
184
|
+
router.requestListener(req, res);
|
|
185
185
|
});
|
|
186
186
|
|
|
187
187
|
describe('hooks', function () {
|
|
@@ -207,7 +207,7 @@ describe('TrieRouter', function () {
|
|
|
207
207
|
});
|
|
208
208
|
const req = createRequestMock();
|
|
209
209
|
const res = createResponseMock();
|
|
210
|
-
router.
|
|
210
|
+
router.requestListener(req, res);
|
|
211
211
|
const result = await res.getBody();
|
|
212
212
|
expect(result).to.be.eq(body);
|
|
213
213
|
expect(order).to.be.eql(['preHandler1', 'preHandler2', 'handler']);
|
|
@@ -235,7 +235,7 @@ describe('TrieRouter', function () {
|
|
|
235
235
|
});
|
|
236
236
|
const req = createRequestMock();
|
|
237
237
|
const res = createResponseMock();
|
|
238
|
-
router.
|
|
238
|
+
router.requestListener(req, res);
|
|
239
239
|
const result = await res.getBody();
|
|
240
240
|
expect(result).to.be.eq(body);
|
|
241
241
|
expect(order).to.be.eql(['handler', 'postHandler1', 'postHandler2']);
|
|
@@ -266,7 +266,7 @@ describe('TrieRouter', function () {
|
|
|
266
266
|
});
|
|
267
267
|
const req = createRequestMock();
|
|
268
268
|
const res = createResponseMock();
|
|
269
|
-
router.
|
|
269
|
+
router.requestListener(req, res);
|
|
270
270
|
const result = await res.getBody();
|
|
271
271
|
expect(result).to.be.eq(body);
|
|
272
272
|
expect(order).to.be.eql(['preHandler1', 'preHandler2', 'handler']);
|
|
@@ -301,7 +301,7 @@ describe('TrieRouter', function () {
|
|
|
301
301
|
});
|
|
302
302
|
const req = createRequestMock();
|
|
303
303
|
const res = createResponseMock();
|
|
304
|
-
router.
|
|
304
|
+
router.requestListener(req, res);
|
|
305
305
|
const result = await res.getBody();
|
|
306
306
|
expect(result).to.be.eq(body);
|
|
307
307
|
expect(order).to.be.eql(['handler', 'postHandler1', 'postHandler2']);
|
|
@@ -331,7 +331,7 @@ describe('TrieRouter', function () {
|
|
|
331
331
|
});
|
|
332
332
|
const req = createRequestMock();
|
|
333
333
|
const res = createResponseMock();
|
|
334
|
-
router.
|
|
334
|
+
router.requestListener(req, res);
|
|
335
335
|
const result = await res.getBody();
|
|
336
336
|
expect(result).to.be.eq(body);
|
|
337
337
|
expect(order).to.be.eql(['preHandler1', 'preHandler2', 'handler']);
|
|
@@ -361,7 +361,7 @@ describe('TrieRouter', function () {
|
|
|
361
361
|
});
|
|
362
362
|
const req = createRequestMock();
|
|
363
363
|
const res = createResponseMock();
|
|
364
|
-
router.
|
|
364
|
+
router.requestListener(req, res);
|
|
365
365
|
const result = await res.getBody();
|
|
366
366
|
expect(result).to.be.eq(body);
|
|
367
367
|
expect(order).to.be.eql(['handler', 'postHandler1', 'postHandler2']);
|
|
@@ -391,7 +391,7 @@ describe('TrieRouter', function () {
|
|
|
391
391
|
});
|
|
392
392
|
const req = createRequestMock();
|
|
393
393
|
const res = createResponseMock();
|
|
394
|
-
router.
|
|
394
|
+
router.requestListener(req, res);
|
|
395
395
|
const result = await res.getBody();
|
|
396
396
|
expect(result).to.be.eq(preHandlerBody);
|
|
397
397
|
expect(result).not.to.be.eq(handlerBody);
|
|
@@ -421,7 +421,7 @@ describe('TrieRouter', function () {
|
|
|
421
421
|
});
|
|
422
422
|
const req = createRequestMock();
|
|
423
423
|
const res = createResponseMock();
|
|
424
|
-
router.
|
|
424
|
+
router.requestListener(req, res);
|
|
425
425
|
const result = await res.getBody();
|
|
426
426
|
expect(result).not.to.be.eq(handlerBody);
|
|
427
427
|
expect(result).to.be.eq(postHandlerBody);
|
|
@@ -448,7 +448,7 @@ describe('TrieRouter', function () {
|
|
|
448
448
|
});
|
|
449
449
|
const req = createRequestMock();
|
|
450
450
|
const res = createResponseMock();
|
|
451
|
-
router.
|
|
451
|
+
router.requestListener(req, res);
|
|
452
452
|
const result = await res.getBody();
|
|
453
453
|
expect(result).to.be.eq(body);
|
|
454
454
|
expect(order).to.be.eql(['preHandler', 'handler', 'postHandler']);
|