Роутер, контролери та сервіси
Що робить роутер
Роутер має мапінг між URL та відповідним обробником запиту. Наприклад, коли користувач вашого вебсайту з браузера запитує адресу /some-path
чи /other-path
, чи /path-with/:parameter
і т.д. - таким чином він повідомляє Ditsmod-застосунок, що хоче отримати певний ресурс, або хоче здійснити певну зміну на сайті. Щоб Ditsmod-застосунок знав, що саме треба робити в даних випадках, у його коді потрібно прописувати відповідні обробники запитів. Тобто, якщо запитують /some-path
, значить треба виконати певну функцію; якщо запитують /other-path
, значить треба виконати іншу функцію і т.д. Коли прописують подібну відповідність між адресою та її обробником - це і є процес створення мапінгу між URL та відповідним обробником запиту.
Хоча вам не прийдеться вручну писати цей мапінг, але для загального уявлення роботи роутера, у дуже спрощеному вигляді його можна уявити так:
const routes = new Map<string, Function>();
routes.set('/some-path', function() { /** обробка запиту... **/ });
routes.set('/other-path', function() { /** обробка запиту... **/ });
routes.set('/path-with/:parameter', function() { /** обробка запиту... **/ });
// ...
Зразу після того, як Node.js отримує HTTP-запит і передає його в Ditsmod, URL запиту розбивається на дві частини, які розділяються знаком питання (якщо він є). Перша частина завжди містить так званий path, а друга частина - query-параметри, якщо URL містить знак питання.
Задача роутера полягає в тому, щоб знайти обробник HTTP-запиту по path. У дуже спрощеному вигляді цей процес можна уявити так:
const path = '/some-path';
const handle = routes.get(path);
// ...
// І потім цей обробник викликається у функції, що прослуховує HTTP-запити.
if (handle) {
handle();
}
У більшості випадків, обробник запиту викликає метод контролера.
Що являє собою контролер
Мапінг між URL та обробником запиту формується на основі метаданих, які закріп ляються за методами контролерів. TypeScript клас стає контролером Ditsmod завдяки декоратору controller
:
import { controller } from '@ditsmod/core';
@controller()
export class SomeController {}
Файли контролерів рекомендується називати із закінченням *.controller.ts
, а імена їхніх класів - із закінченням *Controller
.
Ditsmod забезпечує роботу контролерів у двох альтернативних режимах:
- Injector-scoped контролер (по-дефолту). HTTP-запит він отримує з інжектора.
- Context-scoped контролер. HTTP-запит (разом з іншими контекстними даними) він отримує у якості аргументу, що передається до методу класу.
Перший режим більш зручний і більш безпечний, коли потрібно працювати в контексті поточного HTTP-запиту (клієнт надає певний ідентифікатор, який необхідно враховувати для формування відповіді). Др угий режим роботи помітно швидший (приблизно на 15-20%) і споживає менше пам'яті, але контекст запиту не можна зберігати у властивостях інстансу контролера, бо цей інстанс може одночасно використовуватись для інших клієнтів.
Щоб контролер працював в режимі context-scoped, в його метаданих потрібно вказати { scope: 'ctx' }
:
import { controller } from '@ditsmod/core';
@controller({ scope: 'ctx' })
export class SomeController {}