Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@e22m4u/js-trie-router

Package Overview
Dependencies
Maintainers
0
Versions
17
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@e22m4u/js-trie-router - npm Package Compare versions

Comparing version 0.0.2 to 0.0.3

2

examples/cookie-parsing-example.js

@@ -18,3 +18,3 @@ import http from 'http';

const server = new http.Server();
server.on('request', router.requestHandler);
server.on('request', router.requestListener);

@@ -21,0 +21,0 @@ // слушаем входящие запросы

@@ -18,3 +18,3 @@ import http from 'http';

const server = new http.Server();
server.on('request', router.requestHandler);
server.on('request', router.requestListener);

@@ -21,0 +21,0 @@ // слушаем входящие запросы

@@ -18,3 +18,3 @@ import http from 'http';

const server = new http.Server();
server.on('request', router.requestHandler);
server.on('request', router.requestListener);

@@ -21,0 +21,0 @@ // слушаем входящие запросы

@@ -30,3 +30,3 @@ import http from 'http';

const server = new http.Server();
server.on('request', router.requestHandler);
server.on('request', router.requestListener);

@@ -33,0 +33,0 @@ // слушаем входящие запросы

{
"name": "@e22m4u/js-trie-router",
"version": "0.0.2",
"description": "Trie-based router for Node.js",
"version": "0.0.3",
"description": "Trie-роутер для Node.js",
"type": "module",

@@ -6,0 +6,0 @@ "main": "src/index.js",

## @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
## Установка

@@ -19,21 +19,21 @@ ```bash

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!';

@@ -43,4 +43,4 @@ },

server.on('request', router.requestHandler);
server.listen(3000, 'localhost');
server.on('request', router.requestListener); // подключение роутера
server.listen(3000, 'localhost'); // прослушивание запросов

@@ -50,22 +50,24 @@ // 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 possible values of RequestContext properties.
Пример доступа к контексту из обработчика маршрута.
```js
router.defineRoute({
method: 'get',
method: 'GET',
path: '/users/:id',

@@ -81,3 +83,3 @@ handler(ctx) {

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"

@@ -90,5 +92,8 @@ console.log(ctx.pathname); // "/users/10"

### Sending response
### Отправка ответа
Return values of a route handler will be sent as described below.
Возвращаемое значение обработчика маршрута используется в качестве ответа
сервера. Тип значения влияет на представление возвращаемых данных. Например,
если результатом будет являться тип `object`, то такое значение автоматически
сериализуется в JSON.

@@ -104,10 +109,9 @@ | value | content-type |

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
},

@@ -117,4 +121,4 @@ });

If the `ServerResponse` has been sent manually, then a return
value of the route handler will be ignored.
Контекст запроса `ctx` содержит нативный экземпляр класса `ServerResponse`,
который может быть использован для ручного управления ответом.

@@ -132,21 +136,26 @@ ```js

### Route hooks
### Хуки маршрута
A route definition allows you to set following hooks:
Определение маршрута методом `defineRoute` позволяет задать хуки
для отслеживания и перехвата входящего запроса и ответа
конкретного маршрута.
- `preHandler` is executed before a route handler.
- `postHandler` is executed after a route handler.
- `preHandler` выполняется перед вызовом обработчика
- `postHandler` выполняется после вызова обработчика
If the `preHandler` hook returns a value other than `undefined`
or `null`, it will be used as the server response.
#### preHandler
Перед вызовом обработчика маршрута может потребоваться выполнение
таких операции как авторизация и проверка параметров запроса. Для
этого можно использовать хук `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!';

@@ -157,6 +166,29 @@ },

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({

@@ -167,4 +199,4 @@ // ...

},
preHandler(ctx, data) {
// after the route handler
postHandler(ctx, data) {
// выполняется после обработчика маршрута
return data.toUpperCase(); // HELLO WORLD!

@@ -175,28 +207,31 @@ },

### 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 the 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` перед командой запуска включает вывод логов.

@@ -207,3 +242,3 @@ ```bash

## Testing
## Тестирование

@@ -214,11 +249,4 @@ ```bash

## Contribution
## Лицензия
- Bug fixes.
- Grammar correction.
- Documentation improvements.
- Vulnerability fixes.
## License
MIT

@@ -14,3 +14,3 @@ import HttpErrors from 'http-errors';

*/
export const METHODS_WITH_BODY = ['post', 'put', 'patch', 'delete'];
export const METHODS_WITH_BODY = ['POST', 'PUT', 'PATCH', 'DELETE'];

@@ -104,3 +104,3 @@ /**

parse(req) {
if (!METHODS_WITH_BODY.includes(req.method.toLowerCase())) {
if (!METHODS_WITH_BODY.includes(req.method.toUpperCase())) {
this.debug(

@@ -107,0 +107,0 @@ 'Body parsing was skipped for the %s request.',

@@ -73,3 +73,3 @@ import {Errorf} from '@e22m4u/js-format';

get method() {
return this.req.method.toLowerCase();
return this.req.method.toUpperCase();
}

@@ -76,0 +76,0 @@

@@ -91,8 +91,8 @@ import {expect} from './chai.js';

describe('method', function () {
it('returns the method name in lower case', function () {
const req = createRequestMock({method: 'POST'});
it('returns the method name in upper case', function () {
const req = createRequestMock({method: 'post'});
const res = createResponseMock();
const cnt = new ServiceContainer();
const ctx = new RequestContext(cnt, req, res);
expect(ctx.method).to.be.eq('post');
expect(ctx.method).to.be.eq('POST');
});

@@ -99,0 +99,0 @@ });

@@ -64,3 +64,3 @@ import {Route} from './route.js';

);
const triePath = `${req.method.toLowerCase()}/${requestPath}`;
const triePath = `${req.method.toUpperCase()}/${requestPath}`;
const resolved = this._trie.match(triePath);

@@ -67,0 +67,0 @@ if (resolved) {

@@ -25,15 +25,15 @@ import {Errorf} from '@e22m4u/js-format';

* @type {{
* DELETE: 'delete',
* POST: 'post',
* GET: 'get',
* PUT: 'put',
* PATCH: 'patch',
* GET: 'GET',
* POST: 'POST',
* PUT: 'PUT',
* PATCH: 'PATCH',
* DELETE: 'DELETE',
* }}
*/
export const HTTP_METHOD = {
GET: 'get',
POST: 'post',
PUT: 'put',
PATCH: 'patch',
DELETE: 'delete',
GET: 'GET',
POST: 'POST',
PUT: 'PUT',
PATCH: 'PATCH',
DELETE: 'DELETE',
};

@@ -138,3 +138,3 @@

);
this._method = routeDef.method.toLowerCase();
this._method = routeDef.method.toUpperCase();
if (typeof routeDef.path !== 'string')

@@ -141,0 +141,0 @@ throw new Errorf(

@@ -198,9 +198,9 @@ import {Route} from './route.js';

it('sets the option "method" in lowercase to the "method" property', function () {
it('sets the option "method" in upper case to the "method" property', function () {
const route = new Route({
method: 'POST',
method: 'post',
path: '/',
handler: () => undefined,
});
expect(route.method).to.be.eq('post');
expect(route.method).to.be.eq('POST');
});

@@ -207,0 +207,0 @@

@@ -42,3 +42,3 @@ import {Route} from './route.js';

/**
* Request handler.
* Request listener.
*

@@ -52,4 +52,4 @@ * Example:

* const server = new http.Server();
* server.on('request', router.requestHandler); // Sets the request handler.
* server.listen(3000); // Starts listening for connections.
* server.on('request', router.requestListener); // Sets the request listener.
* server.listen(3000); // Starts listening for connections.
* ```

@@ -59,3 +59,3 @@ *

*/
get requestHandler(): RequestListener;
get requestListener(): RequestListener;

@@ -62,0 +62,0 @@ /**

@@ -50,3 +50,3 @@ import {Service} from './service.js';

/**
* Request handler.
* Request listener.
*

@@ -60,4 +60,4 @@ * Example:

* const server = new http.Server();
* server.on('request', router.requestHandler); // Sets the request handler.
* server.listen(3000); // Starts listening for connections.
* server.on('request', router.requestListener); // Sets the request listener.
* server.listen(3000); // Starts listening for connections.
* ```

@@ -67,3 +67,3 @@ *

*/
get requestHandler() {
get requestListener() {
return this._handleRequest.bind(this);

@@ -70,0 +70,0 @@ }

@@ -28,6 +28,6 @@ import {describe} from 'mocha';

describe('requestHandler', function () {
describe('requestListener', function () {
it('to be a function', function () {
const router = new TrieRouter();
expect(typeof router.requestHandler).to.be.eq('function');
expect(typeof router.requestListener).to.be.eq('function');
});

@@ -47,3 +47,3 @@

const res = createResponseMock();
router.requestHandler(req, res);
router.requestListener(req, res);
});

@@ -63,3 +63,3 @@

const res = createResponseMock();
router.requestHandler(req, res);
router.requestListener(req, res);
});

@@ -79,3 +79,3 @@

const res = createResponseMock();
router.requestHandler(req, res);
router.requestListener(req, res);
});

@@ -95,3 +95,3 @@

const res = createResponseMock();
router.requestHandler(req, res);
router.requestListener(req, res);
});

@@ -112,3 +112,3 @@

const res = createResponseMock();
router.requestHandler(req, res);
router.requestListener(req, res);
});

@@ -129,3 +129,3 @@

const res = createResponseMock();
router.requestHandler(req, res);
router.requestListener(req, res);
});

@@ -148,3 +148,3 @@

const res = createResponseMock();
router.requestHandler(req, res);
router.requestListener(req, res);
});

@@ -169,3 +169,3 @@

});
router.requestHandler(req, res);
router.requestListener(req, res);
});

@@ -193,3 +193,3 @@

});
router.requestHandler(req, res);
router.requestListener(req, res);
});

@@ -220,3 +220,3 @@

const res = createResponseMock();
router.requestHandler(req, res);
router.requestListener(req, res);
const result = await res.getBody();

@@ -249,3 +249,3 @@ expect(result).to.be.eq(body);

const res = createResponseMock();
router.requestHandler(req, res);
router.requestListener(req, res);
const result = await res.getBody();

@@ -281,3 +281,3 @@ expect(result).to.be.eq(body);

const res = createResponseMock();
router.requestHandler(req, res);
router.requestListener(req, res);
const result = await res.getBody();

@@ -317,3 +317,3 @@ expect(result).to.be.eq(body);

const res = createResponseMock();
router.requestHandler(req, res);
router.requestListener(req, res);
const result = await res.getBody();

@@ -348,3 +348,3 @@ expect(result).to.be.eq(body);

const res = createResponseMock();
router.requestHandler(req, res);
router.requestListener(req, res);
const result = await res.getBody();

@@ -379,3 +379,3 @@ expect(result).to.be.eq(body);

const res = createResponseMock();
router.requestHandler(req, res);
router.requestListener(req, res);
const result = await res.getBody();

@@ -410,3 +410,3 @@ expect(result).to.be.eq(body);

const res = createResponseMock();
router.requestHandler(req, res);
router.requestListener(req, res);
const result = await res.getBody();

@@ -441,3 +441,3 @@ expect(result).to.be.eq(preHandlerBody);

const res = createResponseMock();
router.requestHandler(req, res);
router.requestListener(req, res);
const result = await res.getBody();

@@ -469,3 +469,3 @@ expect(result).not.to.be.eq(handlerBody);

const res = createResponseMock();
router.requestHandler(req, res);
router.requestListener(req, res);
const result = await res.getBody();

@@ -472,0 +472,0 @@ expect(result).to.be.eq(body);

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc