@e22m4u/js-trie-router 0.0.2 → 0.0.3
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 +109 -81
- 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 +2 -2
- 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.md
CHANGED
|
@@ -1,70 +1,72 @@
|
|
|
1
1
|
## @e22m4u/js-trie-router
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
[Trie](https://en.wikipedia.org/wiki/Trie)
|
|
3
|
+
ES-модуль HTTP роутера для Node.js, использующий
|
|
4
|
+
[Trie](https://en.wikipedia.org/wiki/Trie)
|
|
5
|
+
для разрешения маршрутов.
|
|
5
6
|
|
|
6
|
-
-
|
|
7
|
-
-
|
|
8
|
-
-
|
|
9
|
-
-
|
|
10
|
-
-
|
|
11
|
-
- Asynchronous request handler.
|
|
7
|
+
- Поддержка [path-to-regexp](https://github.com/pillarjs/path-to-regexp) синтаксиса.
|
|
8
|
+
- Автоматический парсинг JSON-тела запроса.
|
|
9
|
+
- Парсинг строки запроса и заголовка `cookie`.
|
|
10
|
+
- Поддержка `preHandler` и `postHandler` хуков.
|
|
11
|
+
- Позволяет использовать асинхронные обработчики.
|
|
12
12
|
|
|
13
|
-
##
|
|
13
|
+
## Установка
|
|
14
14
|
|
|
15
15
|
```bash
|
|
16
16
|
npm install @e22m4u/js-trie-router
|
|
17
17
|
```
|
|
18
18
|
|
|
19
|
-
|
|
20
|
-
|
|
19
|
+
Для загрузки ES-модуля требуется установить `"type": "module"` в файле
|
|
20
|
+
`package.json`, или использовать `.mjs` расширение.
|
|
21
21
|
|
|
22
|
-
##
|
|
22
|
+
## Обзор
|
|
23
23
|
|
|
24
|
-
|
|
24
|
+
Базовый пример создания экземпляра роутера, объявления маршрута
|
|
25
|
+
и передачи слушателя запросов `http` серверу.
|
|
25
26
|
|
|
26
27
|
```js
|
|
27
28
|
import http from 'http';
|
|
28
|
-
import {TrieRouter} from '
|
|
29
|
-
import {HTTP_METHOD} from '../src/route.js';
|
|
29
|
+
import {TrieRouter} from '@e22m4u/js-path-trie';
|
|
30
30
|
|
|
31
|
-
const server = new http.Server(); //
|
|
32
|
-
const router = new TrieRouter(); //
|
|
31
|
+
const server = new http.Server(); // создание экземпляра HTTP сервера
|
|
32
|
+
const router = new TrieRouter(); // создание экземпляра роутера
|
|
33
33
|
|
|
34
34
|
router.defineRoute({
|
|
35
|
-
method:
|
|
36
|
-
path: '/', //
|
|
37
|
-
handler(ctx) { //
|
|
35
|
+
method: 'GET', // метод запроса "GET", "POST" и т.д.
|
|
36
|
+
path: '/', // шаблон пути, пример "/user/:id"
|
|
37
|
+
handler(ctx) { // обработчик маршрута
|
|
38
38
|
return 'Hello world!';
|
|
39
39
|
},
|
|
40
40
|
});
|
|
41
41
|
|
|
42
|
-
server.on('request', router.
|
|
43
|
-
server.listen(3000, 'localhost');
|
|
42
|
+
server.on('request', router.requestListener); // подключение роутера
|
|
43
|
+
server.listen(3000, 'localhost'); // прослушивание запросов
|
|
44
44
|
|
|
45
45
|
// Open in browser http://localhost:3000
|
|
46
46
|
```
|
|
47
47
|
|
|
48
|
-
###
|
|
48
|
+
### Контекст запроса
|
|
49
49
|
|
|
50
|
-
|
|
50
|
+
Первый параметр обработчика маршрута принимает экземпляр класса
|
|
51
|
+
`RequestContext` с набором свойств, содержащих разобранные
|
|
52
|
+
данные входящего запроса.
|
|
51
53
|
|
|
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`
|
|
54
|
+
- `container: ServiceContainer` экземпляр [сервис-контейнера](https://npmjs.com/package/@e22m4u/js-service)
|
|
55
|
+
- `req: IncomingMessage` нативный поток запроса модуля `http`
|
|
56
|
+
- `res: ServerResponse` нативный поток ответа модуля `http`
|
|
57
|
+
- `params: ParsedParams` объект ключ-значение с параметрами пути
|
|
58
|
+
- `query: ParsedQuery` объект ключ-значение с параметрами строки запроса
|
|
59
|
+
- `headers: ParsedHeaders` объект ключ-значение с заголовками запроса
|
|
60
|
+
- `cookie: ParsedCookie` объект ключ-значение разобранного заголовка `cookie`
|
|
61
|
+
- `method: string` метод запроса в верхнем регистре, например `GET`, `POST` и т.д.
|
|
62
|
+
- `path: string` путь включающий строку запроса, например `/myPath?foo=bar`
|
|
63
|
+
- `pathname: string` путь запроса, например `/myMath`
|
|
62
64
|
|
|
63
|
-
|
|
65
|
+
Пример доступа к контексту из обработчика маршрута.
|
|
64
66
|
|
|
65
67
|
```js
|
|
66
68
|
router.defineRoute({
|
|
67
|
-
method: '
|
|
69
|
+
method: 'GET',
|
|
68
70
|
path: '/users/:id',
|
|
69
71
|
handler(ctx) {
|
|
70
72
|
// GET /users/10?include=city
|
|
@@ -75,7 +77,7 @@ router.defineRoute({
|
|
|
75
77
|
console.log(ctx.query); // {include: 'city'}
|
|
76
78
|
console.log(ctx.headers); // {cookie: 'foo=bar; baz=qux;'}
|
|
77
79
|
console.log(ctx.cookie); // {foo: 'bar', baz: 'qux'}
|
|
78
|
-
console.log(ctx.method); // "
|
|
80
|
+
console.log(ctx.method); // "GET"
|
|
79
81
|
console.log(ctx.path); // "/users/10?include=city"
|
|
80
82
|
console.log(ctx.pathname); // "/users/10"
|
|
81
83
|
// ...
|
|
@@ -83,9 +85,12 @@ router.defineRoute({
|
|
|
83
85
|
});
|
|
84
86
|
```
|
|
85
87
|
|
|
86
|
-
###
|
|
88
|
+
### Отправка ответа
|
|
87
89
|
|
|
88
|
-
|
|
90
|
+
Возвращаемое значение обработчика маршрута используется в качестве ответа
|
|
91
|
+
сервера. Тип значения влияет на представление возвращаемых данных. Например,
|
|
92
|
+
если результатом будет являться тип `object`, то такое значение автоматически
|
|
93
|
+
сериализуется в JSON.
|
|
89
94
|
|
|
90
95
|
| value | content-type |
|
|
91
96
|
|-----------|--------------------------|
|
|
@@ -96,20 +101,19 @@ Return values of a route handler will be sent as described below.
|
|
|
96
101
|
| `Buffer` | application/octet-stream |
|
|
97
102
|
| `Stream` | application/octet-stream |
|
|
98
103
|
|
|
99
|
-
|
|
104
|
+
Пример возвращаемого значения обработчиком маршрута.
|
|
100
105
|
|
|
101
106
|
```js
|
|
102
|
-
router.defineRoute({
|
|
107
|
+
router.defineRoute({ // регистрация маршрута
|
|
103
108
|
// ...
|
|
104
|
-
handler(ctx) {
|
|
105
|
-
//
|
|
106
|
-
return {foo: 'bar'};
|
|
109
|
+
handler(ctx) { // обработчик входящего запроса
|
|
110
|
+
return {foo: 'bar'}; // ответ будет представлен в виде JSON
|
|
107
111
|
},
|
|
108
112
|
});
|
|
109
113
|
```
|
|
110
114
|
|
|
111
|
-
|
|
112
|
-
|
|
115
|
+
Контекст запроса `ctx` содержит нативный экземпляр класса `ServerResponse`,
|
|
116
|
+
который может быть использован для ручного управления ответом.
|
|
113
117
|
|
|
114
118
|
```js
|
|
115
119
|
router.defineRoute({
|
|
@@ -122,32 +126,60 @@ router.defineRoute({
|
|
|
122
126
|
});
|
|
123
127
|
```
|
|
124
128
|
|
|
125
|
-
###
|
|
129
|
+
### Хуки маршрута
|
|
130
|
+
|
|
131
|
+
Определение маршрута методом `defineRoute` позволяет задать хуки
|
|
132
|
+
для отслеживания и перехвата входящего запроса и ответа
|
|
133
|
+
конкретного маршрута.
|
|
126
134
|
|
|
127
|
-
|
|
135
|
+
- `preHandler` выполняется перед вызовом обработчика
|
|
136
|
+
- `postHandler` выполняется после вызова обработчика
|
|
128
137
|
|
|
129
|
-
|
|
130
|
-
- `postHandler` is executed after a route handler.
|
|
138
|
+
#### preHandler
|
|
131
139
|
|
|
132
|
-
|
|
133
|
-
|
|
140
|
+
Перед вызовом обработчика маршрута может потребоваться выполнение
|
|
141
|
+
таких операции как авторизация и проверка параметров запроса. Для
|
|
142
|
+
этого можно использовать хук `preHandler`.
|
|
134
143
|
|
|
135
144
|
```js
|
|
136
|
-
router.defineRoute({
|
|
145
|
+
router.defineRoute({ // регистрация маршрута
|
|
137
146
|
// ...
|
|
138
147
|
preHandler(ctx) {
|
|
139
|
-
|
|
148
|
+
// вызывается перед обработчиком
|
|
149
|
+
console.log(`Incoming request ${ctx.method} ${ctx.path}`);
|
|
150
|
+
// Incoming request GET /myPath
|
|
140
151
|
},
|
|
141
152
|
handler(ctx) {
|
|
142
|
-
// the request handler will be skipped because
|
|
143
|
-
// the "preHandler" hook returns a non-empty value
|
|
144
153
|
return 'Hello world!';
|
|
145
154
|
},
|
|
146
155
|
});
|
|
147
156
|
```
|
|
148
157
|
|
|
149
|
-
|
|
150
|
-
|
|
158
|
+
Если хук `preHandler` возвращает значение отличное от `undefined` и `null`,
|
|
159
|
+
то такое значение будет использовано в качестве ответа сервера, а вызов
|
|
160
|
+
обработчика маршрута будет пропущен.
|
|
161
|
+
|
|
162
|
+
```js
|
|
163
|
+
router.defineRoute({ // регистрация маршрута
|
|
164
|
+
// ...
|
|
165
|
+
preHandler(ctx) {
|
|
166
|
+
// возвращение ответа сервера
|
|
167
|
+
return 'Are you authorized?';
|
|
168
|
+
},
|
|
169
|
+
handler(ctx) {
|
|
170
|
+
// данный обработчик не вызывается, так как
|
|
171
|
+
// хук "preHandler" уже отправил ответ
|
|
172
|
+
},
|
|
173
|
+
});
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
#### postHandler
|
|
177
|
+
|
|
178
|
+
Возвращаемое значение обработчика маршрута передается вторым аргументом
|
|
179
|
+
хука `postHandler`. По аналогии с `preHandler`, если возвращаемое
|
|
180
|
+
значение отличается от `undefined` и `null`, то такое значение будет
|
|
181
|
+
использовано в качестве ответа сервера. Это может быть полезно для
|
|
182
|
+
модификации возвращаемого ответа.
|
|
151
183
|
|
|
152
184
|
```js
|
|
153
185
|
router.defineRoute({
|
|
@@ -155,57 +187,53 @@ router.defineRoute({
|
|
|
155
187
|
handler(ctx) {
|
|
156
188
|
return 'Hello world!';
|
|
157
189
|
},
|
|
158
|
-
|
|
159
|
-
//
|
|
190
|
+
postHandler(ctx, data) {
|
|
191
|
+
// выполняется после обработчика маршрута
|
|
160
192
|
return data.toUpperCase(); // HELLO WORLD!
|
|
161
193
|
},
|
|
162
194
|
});
|
|
163
195
|
```
|
|
164
196
|
|
|
165
|
-
###
|
|
197
|
+
### Глобальные хуки
|
|
166
198
|
|
|
167
|
-
|
|
199
|
+
Экземпляр роутера `TrieRouter` позволяет задать глобальные хуки, которые
|
|
200
|
+
имеют более высокий приоритет перед хуками маршрута, и вызываются
|
|
201
|
+
в первую очередь.
|
|
168
202
|
|
|
169
|
-
- `preHandler`
|
|
170
|
-
- `postHandler`
|
|
203
|
+
- `preHandler` выполняется перед вызовом обработчика
|
|
204
|
+
- `postHandler` выполняется после вызова обработчика
|
|
171
205
|
|
|
172
|
-
|
|
173
|
-
|
|
206
|
+
Добавить глобальные хуки можно методом `addHook` экземпляра роутера,
|
|
207
|
+
где первым параметром передается название хука, а вторым его функция.
|
|
174
208
|
|
|
175
209
|
```js
|
|
176
210
|
router.addHook('preHandler', (ctx) => {
|
|
177
|
-
//
|
|
211
|
+
// вызов перед обработчиком маршрута
|
|
178
212
|
});
|
|
179
213
|
|
|
180
214
|
router.addHook('postHandler', (ctx, data) => {
|
|
181
|
-
//
|
|
215
|
+
// вызов после обработчика маршрута
|
|
182
216
|
});
|
|
183
217
|
```
|
|
184
218
|
|
|
185
|
-
|
|
186
|
-
`undefined`
|
|
219
|
+
Аналогично хукам маршрута, если глобальный хук возвращает значение
|
|
220
|
+
отличное от `undefined` и `null`, то такое значение будет использовано
|
|
221
|
+
как ответ сервера.
|
|
187
222
|
|
|
188
|
-
##
|
|
223
|
+
## Отладка
|
|
189
224
|
|
|
190
|
-
|
|
225
|
+
Установка переменной `DEBUG` перед командой запуска включает вывод логов.
|
|
191
226
|
|
|
192
227
|
```bash
|
|
193
228
|
DEBUG=jsPathTrie* npm run test
|
|
194
229
|
```
|
|
195
230
|
|
|
196
|
-
##
|
|
231
|
+
## Тестирование
|
|
197
232
|
|
|
198
233
|
```bash
|
|
199
234
|
npm run test
|
|
200
235
|
```
|
|
201
236
|
|
|
202
|
-
##
|
|
203
|
-
|
|
204
|
-
- Bug fixes.
|
|
205
|
-
- Grammar correction.
|
|
206
|
-
- Documentation improvements.
|
|
207
|
-
- Vulnerability fixes.
|
|
208
|
-
|
|
209
|
-
## License
|
|
237
|
+
## Лицензия
|
|
210
238
|
|
|
211
239
|
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
|
@@ -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']);
|