@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 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
- A pure ES-module of the Node.js HTTP router that uses the
4
- [Trie](https://en.wikipedia.org/wiki/Trie) for routing.
3
+ *English | [Русский](./README-ru.md)*
5
4
 
6
- - Uses [path-to-regexp](https://github.com/pillarjs/path-to-regexp) syntax.
7
- - Supports path parameters.
8
- - Parses JSON-body automatically.
9
- - Parses a query string and a `cookie` header.
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
- - Asynchronous request handler.
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 an ES-module set `"type": "module"` in the `package.json`
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 "Hello world." example.
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 '../src/index.js';
29
- import {HTTP_METHOD} from '../src/route.js';
30
+ import {TrieRouter} from '@e22m4u/js-trie-router';
30
31
 
31
- const server = new http.Server(); // A Node.js HTTP server.
32
- const router = new TrieRouter(); // A TrieRouter instance.
32
+ const server = new http.Server(); // Node.js HTTP server
33
+ const router = new TrieRouter(); // TrieRouter instance
33
34
 
34
- router.defineRoute({
35
- method: HTTP_METHOD.GET, // Request method.
36
- path: '/', // Path template like "/user/:id".
37
- handler(ctx) { // Request handler.
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.requestHandler);
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
- ### RequestContext
49
+ ### Request context
49
50
 
50
- The first parameter of a route handler is a `RequestContext` instance.
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` is an instance of the [ServiceContainer](https://npmjs.com/package/@e22m4u/js-service)
53
- - `req: IncomingMessage` is a native request from the `http` module
54
- - `res: ServerResponse` is a native response from the `http` module
55
- - `params: ParsedParams` is a key-value object of path parameters
56
- - `query: ParsedQuery` is a key-value object of a parsed query string
57
- - `headers: ParsedHeaders` is a key-value object of request headers
58
- - `cookie: ParsedCookie` is a key-value object of a parsed `cookie` header
59
- - `method: string` is a request method in lower case like `get`, `post` etc.
60
- - `path: string` is a request pathname with a query string
61
- - `pathname: string` is a request pathname without a query 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
- Here are possible values of RequestContext properties.
66
+ Example of accessing the context from a route handler.
64
67
 
65
68
  ```js
66
69
  router.defineRoute({
67
- method: 'get',
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); // "get"
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
- ### Sending response
89
+ ### Response sending
87
90
 
88
- Return values of a route handler will be sent as described below.
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
- Here is an example of a JSON response.
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
- // sends "application/json"
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
- If the `ServerResponse` has been sent manually, then a return
112
- value of the route handler will be ignored.
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
- A route definition allows you to set following hooks:
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
- - `preHandler` is executed before a route handler.
130
- - `postHandler` is executed after a route handler.
140
+ #### preHandler
131
141
 
132
- If the `preHandler` hook returns a value other than `undefined`
133
- or `null`, it will be used as the server response.
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
- return 'Are you authenticated?';
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 return value of the route handler will be passed as the second
150
- argument to the `preHandler` hook.
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
- preHandler(ctx, data) {
159
- // after the route handler
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 `Router` instance allows you to set following global hooks:
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` is executed before each route handler.
170
- - `postHandler` is executed after each route handler.
205
+ - `preHandler` executes before each route handler
206
+ - `postHandler` executes after each route handler
171
207
 
172
- The `addHook` method of a `Router` instance accepts a hook name as the first
173
- parameter and the hook function as the second.
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
- // executes before each route handler
214
+ // before a route handler
178
215
  });
179
216
 
180
217
  router.addHook('postHandler', (ctx, data) => {
181
- // executes after each route handler
218
+ // after a route handler
182
219
  });
183
220
  ```
184
221
 
185
- Similar to a route hook, if a global hook returns a value other than
186
- `undefined` or `null`, that value will be used as the server response.
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
- ## Debug
226
+ ## Debugging
189
227
 
190
- Set environment variable `DEBUG=jsTrieRouter*` before start.
228
+ Set the `DEBUG` variable to enable log output.
191
229
 
192
230
  ```bash
193
- DEBUG=jsPathTrie* npm run test
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.requestHandler);
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.requestHandler);
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.requestHandler);
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.requestHandler);
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.2",
4
- "description": "Trie-based router for Node.js",
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.4.0",
31
- "@commitlint/config-conventional": "~19.2.2",
32
- "@eslint/js": "~9.9.0",
33
- "@types/chai-as-promised": "^8.0.0",
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": "^8.0.0",
37
- "eslint": "~9.9.0",
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": "^50.2.2",
48
+ "eslint-plugin-jsdoc": "~50.3.1",
41
49
  "eslint-plugin-mocha": "~10.5.0",
42
- "globals": "~15.9.0",
43
- "husky": "~9.1.4",
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.5.4"
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 = ['post', 'put', 'patch', 'delete'];
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.toLowerCase())) {
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(),
@@ -70,7 +70,7 @@ export class RequestContext {
70
70
  * @returns {string}
71
71
  */
72
72
  get method() {
73
- return this.req.method.toLowerCase();
73
+ return this.req.method.toUpperCase();
74
74
  }
75
75
 
76
76
  /**
@@ -88,12 +88,12 @@ describe('RequestContext', function () {
88
88
  });
89
89
 
90
90
  describe('method', function () {
91
- it('returns the method name in lower case', function () {
92
- const req = createRequestMock({method: 'POST'});
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('post');
96
+ expect(ctx.method).to.be.eq('POST');
97
97
  });
98
98
  });
99
99
 
@@ -61,7 +61,7 @@ export class RouteRegistry extends Service {
61
61
  req.method.toUpperCase(),
62
62
  requestPath,
63
63
  );
64
- const triePath = `${req.method.toLowerCase()}/${requestPath}`;
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
- * DELETE: 'delete',
26
- * POST: 'post',
27
- * GET: 'get',
28
- * PUT: 'put',
29
- * PATCH: 'patch',
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: 'get',
34
- POST: 'post',
35
- PUT: 'put',
36
- PATCH: 'patch',
37
- DELETE: '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.toLowerCase();
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 lowercase to the "method" property', function () {
198
+ it('sets the option "method" in upper case to the "method" property', function () {
199
199
  const route = new Route({
200
- method: 'POST',
200
+ method: 'post',
201
201
  path: '/',
202
202
  handler: () => undefined,
203
203
  });
204
- expect(route.method).to.be.eq('post');
204
+ expect(route.method).to.be.eq('POST');
205
205
  });
206
206
 
207
207
  it('sets the option "path" to the "path" property', function () {
@@ -39,7 +39,7 @@ export declare class TrieRouter extends Service {
39
39
  defineRoute(routeDef: RouteDefinition): Route;
40
40
 
41
41
  /**
42
- * Request handler.
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.requestHandler); // Sets the request handler.
52
- * server.listen(3000); // Starts listening for connections.
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 requestHandler(): RequestListener;
57
+ get requestListener(): RequestListener;
58
58
 
59
59
  /**
60
60
  * Add hook.
@@ -47,7 +47,7 @@ export class TrieRouter extends Service {
47
47
  }
48
48
 
49
49
  /**
50
- * Request handler.
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.requestHandler); // Sets the request handler.
60
- * server.listen(3000); // Starts listening for connections.
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 requestHandler() {
65
+ get requestListener() {
66
66
  return this._handleRequest.bind(this);
67
67
  }
68
68
 
@@ -25,10 +25,10 @@ describe('TrieRouter', function () {
25
25
  });
26
26
  });
27
27
 
28
- describe('requestHandler', function () {
28
+ describe('requestListener', function () {
29
29
  it('to be a function', function () {
30
30
  const router = new TrieRouter();
31
- expect(typeof router.requestHandler).to.be.eq('function');
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.requestHandler(req, res);
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.requestHandler(req, res);
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.requestHandler(req, res);
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.requestHandler(req, res);
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.requestHandler(req, res);
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.requestHandler(req, res);
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.requestHandler(req, res);
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.requestHandler(req, res);
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.requestHandler(req, res);
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.requestHandler(req, res);
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.requestHandler(req, res);
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.requestHandler(req, res);
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.requestHandler(req, res);
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.requestHandler(req, res);
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.requestHandler(req, res);
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.requestHandler(req, res);
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.requestHandler(req, res);
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.requestHandler(req, res);
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']);