5 January 2012

Маршрутизация запросов в Autodafé

Node.JS
Autodafé — node.js фреймворк, начало читайте в этой статье: habrahabr.ru/blogs/nodejs/135089

Основная часть статьи будет посвящена перенаправлению запросов в autodafe, формированию URL и т. п. Но для начала мне бы хотелось осветить общие принципы работы приложения с подключенными клиентами, для того чтобы было понятнее какую часть рабочего процесса мы будем обсуждать.

Откуда берется пыль


Начнем со схемы, отображающей подключение клиентов к приложению:



На схеме можно увидеть несколько пользователей, которые пользуются различными устройствами и различными браузерами, которые в свою очередь подключаются к приложению по различным протоколам. (В данный момент к autodafe можно подключиться только по http и websockets)

В приложении каждому подключению соответствует один Client. Client создается для каждого http запроса и подключения по websockets. Клиенты с одинаковым идентификатором сессии принадлежат одному экземпляру Session. Обычно одна сессия в приложение соответствует одному браузеру.

Ну и для логического завершения на схеме приведен компонент “users”, который позволяет привязать различные сессии, прошедшие специальную авторизацию к одному объекту UserIdentity. Таким образом в приложении каждый объект UserIdentity соотносится к одному реальному пользователю.



Куда деваются деньги


Итак мы подходим к теме данной статьи: написание маршрутизации. Каждый Client, получив запрос, формирует его в особый вид и отправляет в Router. А он, в свою очередь, пользуясь таблицей маршрутизации ( Route map на схеме ) перенаправляет запрос в нужное действие нужного контроллера.

Таким образом: каждый запрос по любому протоколу перенаправляется, пользуясь таблицей описанной в одном месте



Таблица маршрутизации


В таблице маршрутизации можно указывать:
  • само собой, маршруты перенаправления запросов к действию определенного контроллера
  • параметры для человекопонятных URL
  • методы и протоколы для которых доступны данные действия
  • перенаправление в зависимости от хоста с которого пришел запрос, на какой порт он пришел и т. д.

Таблица маршрутизации служит не только для разбора пришедшего запроса, но и для формирования URL на сервере, что позволяет гибко менять вид URL, делая правки в одном месте.

Контроллеры — это обычные классы. Действия — это методы. Ни один запрос не будет работать, если он не указан в таблице маршрутизации. Таким образом защищаются от вызова методы контроллера, не являющиеся действиями.

Для следующих примеров можно взять приложение Hello World описанное в этой статье. Сейчас в секции router.rules конфигурационного файла лишь одно правило:

router : {
  rules : {
    '' : 'site.index'
  }
}

Ключи секции rules соответствуют части url адреса, которая идет после названия хоста и до параметров запроса, так для url адреса www.example.com/messages/unread?user_id=5 эта часть равна messages/unread.

Значения rules — это путь к действию, которое необходимо выполнить для данного запроса в виде 'контроллер.действие'

router : {
  rules : {
    ''                : 'site.index',
    'messages/unread' : 'dialogs.show_unread_messages'
  }
}


Создание URL



В коде контроллера для создания нужного URL надо пользоваться методом create_url:

this.create_url( 'dialogs.show_unread_messages' ); // вернет '/messages/unread'

Часто ссылки надо вставлять во вью, в качестве шаблонизатора сейчас используется dust, для него написана специальная функция url:

<a href="{#url}dialogs.show_unread_messages{/url}">Непрочитанные сообщения</a>


Передача параметров



Создание ссылки внутри контроллера:

this.create_url( 'dialogs.show_unread_messages', {
  user_id : 5
} );                       // вернет '/messages/unread?user_id=5'

Во вью:

<a href='{#url user_id="5"}dialogs.show_unread_messages{/url}'>Непрочитанные сообщения</a>


Засовываем параметры в путь



Суть: превратить /messages/unread?user_id=5 в /messages/unread/user/5

Секция rules:

rules : {
  '/messages/unread/user/<user_id:\\d+>' : 'dialogs.dialogs.show_unread_messages'
}

Как видно, мы просто определяем название параметра и регулярное выражение которому он должен соответствовать. Ни в контроллере, ни во вью изменений делать не надо.

Фильтруем запросы


Некоторые действия необходимо выполнять, например, только если они пришли через POST запрос или по WebSockets. Это можно указать прямо в таблице.

rules : {
  // запрос сработает только если придет через POST 
  'update_message' : 'dialogs.update_message | post'
}

Вместо post могут быть get, delete и ws. Последние ограничевает вызов только для действий, поступившим по WebSockets

Методы можно группировать через запятую:

rules : {
  // запрос сработает только если придет через POST
  'delete_message' : 'dialogs.delete_message | post, delete'
}

Пробелы не учитываются, так что можно спокойно выравнивать все в красивый вид

Фильтруем запросы по доменному имени и порту

rules : {
  'hostname:m.domain.com port:3000 /' : 'mobile.index'
}

Более подробно данная тема будет раскрыта в готовящемся сайте с документацией

Спасибо за внимание.

PS:


Исходный код на github: autodafe
Приследуйте фреймворк в твиттере @node_autodafe

Если желаете принять участие в разработке или любым способом помочь в развитии фреймворка — пишите в личку или на jifeon at gmail.com
Tags:node.jsjavascriptautodafemvcmysqlormloggingroutingactiverecordwebsockets
Hubs: Node.JS
+4
1.2k 16
Leave a comment
Popular right now
Node.js Developer
from 1,600 to 4,200 $AWWCOR Inc.Remote job
Team Lead (React\Node.js)
to 180,000 ₽SoftMediaLabЕкатеринбургRemote job
Backend (Node.js) Developer
from 280,000 to 440,000 ₽OsomeRemote job
Node.js developer (infrastructure)
from 100,000 to 300,000 ₽ЯндексМосква
Backend разработчик (Node.js)
from 100,000 ₽WazzupRemote job
Top of the last 24 hours