Dancer2 или современное web-приложение на PERL. Часть II

Kate

Administrator
Команда форума

Выбор шаблонного движка​

В предыдущей статье Dancer2 или современное web-приложение на PERL мы поверхностно затронули тему шаблонов. Пришло время разобраться с деталями.
По умолчанию в конфигурации нашего проекта установлен самый базовый шаблонный движок Dancer2::Template::Simple (все ссылки в конце). Он умеет делать только две вещи: интерполировать переменные и подключать макет. Почти для любого приложения этого недостаточно. Хочется использовать циклы, условия и удобно работать со сложными структурами данных. Dancer2 имеет адаптеры к большому количеству популярных модулей для создания шаблонов:
С сайта https://www.perldancer.org/
С сайта https://www.perldancer.org/
В документации активно продвигается самый популярный в среде Perl Template::Toolkit. Это настоящий кухонный комбайн с большими набором встроенных функций, фильтров и прочего. На мой взгляд, для web-приложения у него есть один существенный недостаток: вывод не экранируется по умолчанию. Для того, чтобы преобразовать все HTML-значимые-символы в HTML-сущности, нужно явно применить соответствующий фильтр. А значит получение XSS-уязвимости - дело времени (рано или поздно кто-нибудь из команды обязательно забудет применить нужный фильтр).
После продолжительного времени, проведенного в поисковиках, на форумах и даже в специализированных чатах, я нашел прекрасное современное решение Dancer2::Template::Handlebars (да-да, в Перле много современного, бывает надо просто хорошенько поискать). В нем используется приятный "усатый" синтаксис {{ }}, весь вывод фильтруется по умолчанию, из коробки предоставляются хелперы: with, each, if, unless и, что немаловажно, он легко расширяется с помощью модуля Dancer2::Template::Handlebars::Helpers.
Приступим к подключению. Для начала, в консоли:
cpan Dancer2::Template::Handlebars
Следом пропишем необходимые поля в config.yml:
views: "views" # путь к директории шаблонов
template: "handlebars" # меняем значение на "handlebars"
Теперь необходимо для всех шаблонов и макетов (находятся в директории views) изменить расширение с .tt на .hbs, результат должен быть таким:
9a458426b6b1f8453cb997001e531d61.png

А внутри самих файлов изменить <% var %> на новый синтаксис с фигурными скобками {{ var }}. Код page.hbs:
<h1>Hi!</h1>
<p>You are on page: <b>{{ page }}</b></p>
Открываем http://localhost:5000/pages/11 и видим:
Специальные символы преобразованы в HTML-сущности
Специальные символы преобразованы в HTML-сущности
Догадались в чем проблема? Правильно, HTML-фильтр по умолчанию. Поправить можно легко, для этого надо заключить переменную content в макете layouts/main.hbs в тройные "усы", вот так: {{{ content }}} (таким образом не применяется фильтр). Теперь всё в порядке:
b30b60ec720b24d3bb550bc1344f0152.png

Для тех, кто захочет изучить Dancer2::Template::Handlebars детальнее, в конце будет ссылка. А мы переходим к сессиям.

Сессии​

Фреймворк предлагает различные технологии хранения сессий на выбор:
  • In-memory
  • YAML
  • Cookie
  • База данных
  • Redis/Memcached
  • и другие
Например, Dancer2::Session::YAML, хранящая данные в yml на сервере. При использовании этой технологии в продакшене, следует озаботиться механизмом удаления старых файлов, например через cron.
Начинаем с установки модуля:
cpan Dancer2::Session::YAML
Далее в config.yml:
session: "YAML"

engines:
session:
YAML:
session_dir: "tmp/sessions" # путь к хранилищу
cookie_name: "sessid" # название куки
cookie_duration: 3600 # время жизни куки
is_secure: 1 # только HTTPS
is_http_only: 1 # не доступна JS
Директорию tpm/sessions лучше создать самостоятельно и добавить её в .gitignore.
Работа с сессией происходит с помощью функции session, для записи передаем ей два аргумента, а для чтения один:
# запись
session 'user_info' => {
name => 'Petya',
created => '15.08.2021',
};

# чтение
my $user_info = session 'user_info';
Содержимое файла с сессией будет выглядеть так:
---
user_info:
created: 15.08.2021
name: Petya

Флэш-сообщения​

Лучший способ продемонстрировать работу сессии - использовать флэш-сообщения. Из коробки Dancer их не предоставляет, но существует несколько плагинов, реализующих данную функцию. Например Dancer2::plugin::FlashNote:
cpan Dancer2::plugin::FlashNote
Config.yml:
plugins:
FlashNote:
queue: "single" # хранится только одно сообщение
dequeue: "when_used" # сообщение удаляется при использовании
Подключаем модуль вверху lib/MyApp.pm:
use Dancer2::plugin::FlashNote;
И в наше распоряжение попадает функция flash, плюс одноименная переменная будет доступна в шаблонах.

Соединяем полученные знания​

Для закрепления материала реализуем следующую задачу:
  • Создание роута logout, который установит флэш-сообщение и перенаправит пользователя на главную.
  • Создание главной страницы, на которой будет выводится флэш-сообщение при его наличии.
Приведу весь код для lib/MyApp.pm:
package MyApp;

use Dancer2;
use Dancer2::plugin::FlashNote;

our $VERSION = '0.1';

get '/' => sub {
template 'index'; # шаблон главной страницы
};

get '/logout' => sub {
flash 'Bye bye!'; # установка флэш-сообщения

redirect '/'; # перенаправление на главную
};

get '/pages/:page[Int]' => sub {
my $page = route_parameters->get('page');

template 'page', {
page => $page,
};
};

true;

И код шаблона index.hbs с использованием блока if:
{{#if flash }}
<p><b>{{ flash }}</b></p>
{{/if }}

<p>Let's dance!</p>
Теперь при открытии http://localhost:5000/logout мы окажемся на главной и увидим:
b1aaf44cb8e72640ac04745c54bd8265.png

При повторном обращении к главной, сообщение пропадет.

Итог​

Мы преодолели немалый путь и научились создавать роуты и шаблоны для них, использовать сессии и флеш-сообщения, а также расширять стандартную функциональность фреймворка плагинами. В следующей части поговорим про работу с базой, модели и миграции.
Весь код, который был написан в процессе создания этой статьи выложен на гитхаб (ссылка в конце). Создавайте свои web-приложения легко и танцуйте вместе с Perl и Dancer2!

Серия статей про Dancer2​

  • Часть I - установка, роутинг и шаблоны
  • Часть II (текущая) - выбор шаблонного движка, сессии и флэш-сообщения

Ссылки​


 
Сверху