|
|
@@ -1,70 +1,72 @@
|
|
|
## @e22m4u/js-trie-router
|
|
|
|
|
|
-A pure ES-module of the Node.js HTTP router that uses the
|
|
|
-[Trie](https://en.wikipedia.org/wiki/Trie) for routing.
|
|
|
+ES-модуль HTTP роутера для Node.js, использующий
|
|
|
+[Trie](https://en.wikipedia.org/wiki/Trie)
|
|
|
+для разрешения маршрутов.
|
|
|
|
|
|
-- Uses [path-to-regexp](https://github.com/pillarjs/path-to-regexp) syntax.
|
|
|
-- Supports path parameters.
|
|
|
-- Parses JSON-body automatically.
|
|
|
-- Parses a query string and a `cookie` header.
|
|
|
-- Supports `preHandler` and `postHandler` hooks.
|
|
|
-- Asynchronous request handler.
|
|
|
+- Поддержка [path-to-regexp](https://github.com/pillarjs/path-to-regexp) синтаксиса.
|
|
|
+- Автоматический парсинг JSON-тела запроса.
|
|
|
+- Парсинг строки запроса и заголовка `cookie`.
|
|
|
+- Поддержка `preHandler` и `postHandler` хуков.
|
|
|
+- Позволяет использовать асинхронные обработчики.
|
|
|
|
|
|
-## Installation
|
|
|
+## Установка
|
|
|
|
|
|
```bash
|
|
|
npm install @e22m4u/js-trie-router
|
|
|
```
|
|
|
|
|
|
-To load an ES-module set `"type": "module"` in the `package.json`
|
|
|
-or use the `.mjs` extension.
|
|
|
+Для загрузки ES-модуля требуется установить `"type": "module"` в файле
|
|
|
+`package.json`, или использовать `.mjs` расширение.
|
|
|
|
|
|
-## Overview
|
|
|
+## Обзор
|
|
|
|
|
|
-A basic "Hello world." example.
|
|
|
+Базовый пример создания экземпляра роутера, объявления маршрута
|
|
|
+и передачи слушателя запросов `http` серверу.
|
|
|
|
|
|
```js
|
|
|
import http from 'http';
|
|
|
-import {TrieRouter} from '../src/index.js';
|
|
|
-import {HTTP_METHOD} from '../src/route.js';
|
|
|
+import {TrieRouter} from '@e22m4u/js-path-trie';
|
|
|
|
|
|
-const server = new http.Server(); // A Node.js HTTP server.
|
|
|
-const router = new TrieRouter(); // A TrieRouter instance.
|
|
|
+const server = new http.Server(); // создание экземпляра HTTP сервера
|
|
|
+const router = new TrieRouter(); // создание экземпляра роутера
|
|
|
|
|
|
router.defineRoute({
|
|
|
- method: HTTP_METHOD.GET, // Request method.
|
|
|
- path: '/', // Path template like "/user/:id".
|
|
|
- handler(ctx) { // Request handler.
|
|
|
+ method: 'GET', // метод запроса "GET", "POST" и т.д.
|
|
|
+ path: '/', // шаблон пути, пример "/user/:id"
|
|
|
+ handler(ctx) { // обработчик маршрута
|
|
|
return 'Hello world!';
|
|
|
},
|
|
|
});
|
|
|
|
|
|
-server.on('request', router.requestHandler);
|
|
|
-server.listen(3000, 'localhost');
|
|
|
+server.on('request', router.requestListener); // подключение роутера
|
|
|
+server.listen(3000, 'localhost'); // прослушивание запросов
|
|
|
|
|
|
// Open in browser http://localhost:3000
|
|
|
```
|
|
|
|
|
|
-### RequestContext
|
|
|
+### Контекст запроса
|
|
|
|
|
|
-The first parameter of a route handler is a `RequestContext` instance.
|
|
|
+Первый параметр обработчика маршрута принимает экземпляр класса
|
|
|
+`RequestContext` с набором свойств, содержащих разобранные
|
|
|
+данные входящего запроса.
|
|
|
|
|
|
-- `container: ServiceContainer` is an instance of the [ServiceContainer](https://npmjs.com/package/@e22m4u/js-service)
|
|
|
-- `req: IncomingMessage` is a native request from the `http` module
|
|
|
-- `res: ServerResponse` is a native response from the `http` module
|
|
|
-- `params: ParsedParams` is a key-value object of path parameters
|
|
|
-- `query: ParsedQuery` is a key-value object of a parsed query string
|
|
|
-- `headers: ParsedHeaders` is a key-value object of request headers
|
|
|
-- `cookie: ParsedCookie` is a key-value object of a parsed `cookie` header
|
|
|
-- `method: string` is a request method in lower case like `get`, `post` etc.
|
|
|
-- `path: string` is a request pathname with a query string
|
|
|
-- `pathname: string` is a request pathname without a query string
|
|
|
+- `container: ServiceContainer` экземпляр [сервис-контейнера](https://npmjs.com/package/@e22m4u/js-service)
|
|
|
+- `req: IncomingMessage` нативный поток запроса модуля `http`
|
|
|
+- `res: ServerResponse` нативный поток ответа модуля `http`
|
|
|
+- `params: ParsedParams` объект ключ-значение с параметрами пути
|
|
|
+- `query: ParsedQuery` объект ключ-значение с параметрами строки запроса
|
|
|
+- `headers: ParsedHeaders` объект ключ-значение с заголовками запроса
|
|
|
+- `cookie: ParsedCookie` объект ключ-значение разобранного заголовка `cookie`
|
|
|
+- `method: string` метод запроса в верхнем регистре, например `GET`, `POST` и т.д.
|
|
|
+- `path: string` путь включающий строку запроса, например `/myPath?foo=bar`
|
|
|
+- `pathname: string` путь запроса, например `/myMath`
|
|
|
|
|
|
-Here are example values of RequestContext properties.
|
|
|
+Пример доступа к контексту из обработчика маршрута.
|
|
|
|
|
|
```js
|
|
|
router.defineRoute({
|
|
|
- method: 'get',
|
|
|
+ method: 'GET',
|
|
|
path: '/users/:id',
|
|
|
handler(ctx) {
|
|
|
// GET /users/10?include=city
|
|
|
@@ -75,7 +77,7 @@ router.defineRoute({
|
|
|
console.log(ctx.query); // {include: 'city'}
|
|
|
console.log(ctx.headers); // {cookie: 'foo=bar; baz=qux;'}
|
|
|
console.log(ctx.cookie); // {foo: 'bar', baz: 'qux'}
|
|
|
- console.log(ctx.method); // "get"
|
|
|
+ console.log(ctx.method); // "GET"
|
|
|
console.log(ctx.path); // "/users/10?include=city"
|
|
|
console.log(ctx.pathname); // "/users/10"
|
|
|
// ...
|
|
|
@@ -83,9 +85,12 @@ router.defineRoute({
|
|
|
});
|
|
|
```
|
|
|
|
|
|
-### Sending response
|
|
|
+### Отправка ответа
|
|
|
|
|
|
-Return values of a route handler will be sent as described below.
|
|
|
+Возвращаемое значение обработчика маршрута используется в качестве ответа
|
|
|
+сервера. Тип значения влияет на представление возвращаемых данных. Например,
|
|
|
+если результатом будет являться тип `object`, то такое значение автоматически
|
|
|
+сериализуется в JSON.
|
|
|
|
|
|
| value | content-type |
|
|
|
|-----------|--------------------------|
|
|
|
@@ -96,20 +101,19 @@ Return values of a route handler will be sent as described below.
|
|
|
| `Buffer` | application/octet-stream |
|
|
|
| `Stream` | application/octet-stream |
|
|
|
|
|
|
-Here is an example of a JSON response.
|
|
|
+Пример возвращаемого значения обработчиком маршрута.
|
|
|
|
|
|
```js
|
|
|
-router.defineRoute({
|
|
|
+router.defineRoute({ // регистрация маршрута
|
|
|
// ...
|
|
|
- handler(ctx) {
|
|
|
- // sends "application/json"
|
|
|
- return {foo: 'bar'};
|
|
|
+ handler(ctx) { // обработчик входящего запроса
|
|
|
+ return {foo: 'bar'}; // ответ будет представлен в виде JSON
|
|
|
},
|
|
|
});
|
|
|
```
|
|
|
|
|
|
-If the `ServerResponse` has been sent manually, then a return
|
|
|
-value of the route handler will be ignored.
|
|
|
+Контекст запроса `ctx` содержит нативный экземпляр класса `ServerResponse`,
|
|
|
+который может быть использован для ручного управления ответом.
|
|
|
|
|
|
```js
|
|
|
router.defineRoute({
|
|
|
@@ -122,32 +126,60 @@ router.defineRoute({
|
|
|
});
|
|
|
```
|
|
|
|
|
|
-### Route hooks
|
|
|
+### Хуки маршрута
|
|
|
+
|
|
|
+Определение маршрута методом `defineRoute` позволяет задать хуки
|
|
|
+для отслеживания и перехвата входящего запроса и ответа
|
|
|
+конкретного маршрута.
|
|
|
|
|
|
-A route definition allows you to set following hooks:
|
|
|
+- `preHandler` выполняется перед вызовом обработчика
|
|
|
+- `postHandler` выполняется после вызова обработчика
|
|
|
|
|
|
-- `preHandler` is executed before a route handler.
|
|
|
-- `postHandler` is executed after a route handler.
|
|
|
+#### preHandler
|
|
|
|
|
|
-If the `preHandler` hook returns a value other than `undefined`
|
|
|
-or `null`, it will be used as the server response.
|
|
|
+Перед вызовом обработчика маршрута может потребоваться выполнение
|
|
|
+таких операции как авторизация и проверка параметров запроса. Для
|
|
|
+этого можно использовать хук `preHandler`.
|
|
|
|
|
|
```js
|
|
|
-router.defineRoute({
|
|
|
+router.defineRoute({ // регистрация маршрута
|
|
|
// ...
|
|
|
preHandler(ctx) {
|
|
|
- return 'Are you authenticated?';
|
|
|
+ // вызывается перед обработчиком
|
|
|
+ console.log(`Incoming request ${ctx.method} ${ctx.path}`);
|
|
|
+ // Incoming request GET /myPath
|
|
|
},
|
|
|
handler(ctx) {
|
|
|
- // the request handler will be skipped because
|
|
|
- // the "preHandler" hook returns a non-empty value
|
|
|
return 'Hello world!';
|
|
|
},
|
|
|
});
|
|
|
```
|
|
|
|
|
|
-A return value of the route handler will be passed as the second
|
|
|
-argument to the `preHandler` hook.
|
|
|
+Если хук `preHandler` возвращает значение отличное от `undefined` и `null`,
|
|
|
+то такое значение будет использовано в качестве ответа сервера, а вызов
|
|
|
+обработчика маршрута будет пропущен.
|
|
|
+
|
|
|
+```js
|
|
|
+router.defineRoute({ // регистрация маршрута
|
|
|
+ // ...
|
|
|
+ preHandler(ctx) {
|
|
|
+ // возвращение ответа сервера
|
|
|
+ return 'Are you authorized?';
|
|
|
+ },
|
|
|
+ handler(ctx) {
|
|
|
+ // данный обработчик не вызывается, так как
|
|
|
+ // хук "preHandler" уже отправил ответ
|
|
|
+ },
|
|
|
+});
|
|
|
+```
|
|
|
+
|
|
|
+#### postHandler
|
|
|
+
|
|
|
+Возвращаемое значение обработчика маршрута передается вторым аргументом
|
|
|
+хука `postHandler`. По аналогии с `preHandler`, если возвращаемое
|
|
|
+значение отличается от `undefined` и `null`, то такое значение будет
|
|
|
+использовано в качестве ответа сервера. Это может быть полезно для
|
|
|
+модификации возвращаемого ответа.
|
|
|
|
|
|
```js
|
|
|
router.defineRoute({
|
|
|
@@ -155,57 +187,53 @@ router.defineRoute({
|
|
|
handler(ctx) {
|
|
|
return 'Hello world!';
|
|
|
},
|
|
|
- preHandler(ctx, data) {
|
|
|
- // after the route handler
|
|
|
+ postHandler(ctx, data) {
|
|
|
+ // выполняется после обработчика маршрута
|
|
|
return data.toUpperCase(); // HELLO WORLD!
|
|
|
},
|
|
|
});
|
|
|
```
|
|
|
|
|
|
-### Global hooks
|
|
|
+### Глобальные хуки
|
|
|
|
|
|
-A `Router` instance allows you to set following global hooks:
|
|
|
+Экземпляр роутера `TrieRouter` позволяет задать глобальные хуки, которые
|
|
|
+имеют более высокий приоритет перед хуками маршрута, и вызываются
|
|
|
+в первую очередь.
|
|
|
|
|
|
-- `preHandler` is executed before each route handler.
|
|
|
-- `postHandler` is executed after each route handler.
|
|
|
+- `preHandler` выполняется перед вызовом обработчика
|
|
|
+- `postHandler` выполняется после вызова обработчика
|
|
|
|
|
|
-The `addHook` method of a `Router` instance accepts a hook name as the first
|
|
|
-parameter and a hook function as the second.
|
|
|
+Добавить глобальные хуки можно методом `addHook` экземпляра роутера,
|
|
|
+где первым параметром передается название хука, а вторым его функция.
|
|
|
|
|
|
```js
|
|
|
router.addHook('preHandler', (ctx) => {
|
|
|
- // executes before each route handler
|
|
|
+ // вызов перед обработчиком маршрута
|
|
|
});
|
|
|
|
|
|
router.addHook('postHandler', (ctx, data) => {
|
|
|
- // executes after each route handler
|
|
|
+ // вызов после обработчика маршрута
|
|
|
});
|
|
|
```
|
|
|
|
|
|
-Similar to a route hook, if a global hook returns a value other than
|
|
|
-`undefined` or `null`, that value will be used as the server response.
|
|
|
+Аналогично хукам маршрута, если глобальный хук возвращает значение
|
|
|
+отличное от `undefined` и `null`, то такое значение будет использовано
|
|
|
+как ответ сервера.
|
|
|
|
|
|
-## Debug
|
|
|
+## Отладка
|
|
|
|
|
|
-Set environment variable `DEBUG=jsTrieRouter*` before start.
|
|
|
+Установка переменной `DEBUG` перед командой запуска включает вывод логов.
|
|
|
|
|
|
```bash
|
|
|
DEBUG=jsPathTrie* npm run test
|
|
|
```
|
|
|
|
|
|
-## Testing
|
|
|
+## Тестирование
|
|
|
|
|
|
```bash
|
|
|
npm run test
|
|
|
```
|
|
|
|
|
|
-## Contribution
|
|
|
-
|
|
|
-- Bug fixes.
|
|
|
-- Grammar correction.
|
|
|
-- Documentation improvements.
|
|
|
-- Vulnerability fixes.
|
|
|
-
|
|
|
-## License
|
|
|
+## Лицензия
|
|
|
|
|
|
MIT
|