Наступило лето, пора отпусков, самое время заняться изучением Perl и Dancer, а также написать об этом пост (мой первый на хабре). Очертим круг читателей, которым он может быть полезным и интересным:

  • Всем любителям Perl.

  • Веб-разработчикам.

  • Всем, кто собирается писать на Perl.

Предисловие

Некоторое время назад мне встретилась (на полке заброшенных книг):

Актуальная версия Перла 5.34
Актуальная версия Перла 5.34

Она про версию языка 5.14, но что очень удобно для изучения Перла - код, работающий 15 лет назад, работает и сегодня. Многие примеры всё ещё применимы, а всё устаревшее улавливается и гуглится.

А ещё она написана прекрасным живым языком, легко читается и просто поднимает настроение.

Однако, если вы хотите начать изучение Perl сегодня, то лучше выбрать самое последнее, буквально на днях вышедшее, 8-е издание (все полезные ссылки будут в конце). Поправка: книга "Learning Perl, 8th Edition" написана, отправлена в печать, но ещё не выпущена. Амазон честно пишет "This title has not yet been released").

Язык мне очень понравился своей свободой и гибкостью. И я влюбился, влюбился с первой строчки кода, с первого цикла и первого модуля.

Перл и Web

На сегодняшний день существуют два основных фреймворка для web-разработки на PERL:

  • Dancer2 - микро-фреймворк, расширяется плагинами.

  • Mojolicious - полновесный фреймворк с большим количеством встроенных возможностей.

Оба поддерживаются и обновляются, авторы отвечают на вопросы и участвуют в коммуникации с сообществом. А ещё на странице каждого можно найти гайды и туториалы.

Я решил препарировать Dancer.

С чего начать

Было бы неплохо обзавестись последней версией языка, в этом поможет perlbrew для Nix'ов и berrybrew для Windows (или используйте менеджер пакетов вашей системы: deb, rpm, другие), и утилитой cpan(поставляется вместе с perl) для установки модулей и зависимостей.

Теперь ставим фреймворк:

cpan Dancer2

После установки, в наше распоряжение попадает утилита dancer2, которая создаст базовый скелет приложения:

dancer2 gen -a MyApp
  1. bin - там лежит стартующий файл для запуска Dancer

  2. lib - наш код

  3. public - всё, что доступно из интернета

  4. views - представления

  5. t - тесты

  6. environments - конфиги

  7. config.yml - основной конфиг

  8. cpanfile - зависимости (оказался очень полезным, расскажу в продолжении)

  9. Makefile.PL - для зависимостей и размещения на cpan

  10. MANIFEST.SKIP - для зависимостей и размещения на cpan

  11. MANIFEST - для зависимостей и размещения на cpan

  12. .dancer - для cpan

Теперь запустим тестовый сервер с помощью утилиты plackup(она была установлена вместе с фреймворком):

cd MyApp                      # директория проекта
plackup -p 5000 bin/app.psgi  # запускаем сервер

Открыв http://localhost:5000, вы увидите там справочную страницу dancer с полезными ссылками и базовой информацией о вашем приложении:

Перл танцует
Перл танцует

Dancer2

Dancer2 реализует MVC, правда из коробки не предоставляет инструментов для работы с моделью(это уже реализуется с помощью плагинов). Для работы с представлениями предлагаются движки на выбор. Имеется множество адаптеров ко всем популярным модулям, что позволяет выбрать оптимальный для вас вариант.

Фрейморк предоставляет в пользование набор команд, которые выглядят как ключевые слова(спасибо гибкости Perl), но на самом деле являются функциями-хелперами. Из этих слов выстраивается доменно-специфический язык (DSL), который позволяет декларативно описывать логику:

use Dancer2;
 
get '/' => sub {
    return 'Hello World!';
};
 
start;

Приложение имеет три файла конфигов. Config.yml в корне для всех основных настроек: сессии, куки, шаблоны. И два файла environments/development.yml и environments/production.yml. Первый используется по дефолту при запуске приложения и предназначен для разработки: очень подробное логирование почти всего процесса, вывод логов в консоль и отображение ошибок. Второй: логирование в файл, отключенные ошибки, задействуется в боевой среде и подключается с помощью ключа --env при запуске:

plackup -p 5000 --env production bin/app.psgi

Роутинг

Описываются роуты в файле lib/MyApp.pm с помощью специальных "http глаголов": get, post, put, delete и других, соответствующих основным http методам. Далее идет схема маршрута(роут) и анонимная функция-обработчик, куда будет передано управление при совпадении маршрута:

get '/' => sub {
    return "Let's dance!";
};

Оператор жирной запятой (=>) может ввести в заблуждение людей незнакомых с языком. В Perl он эквивалентен обычной запятой (,) и в данном случае используется лишь для удобочитаемости при разделении аргументов функции get.

В схеме можно описать именованные параметры, обозначив их двоеточием (:), с их помощью реализуются маршруты с динамическими фрагментами:

get '/pages/:page' => sub {
    my $page = route_parameters->get('page');
    return "Welcome to the page:$page";
};

Dancer позволяет дополнительно задать тип этого параметра в квадратных скобках([]). Этой возможностью надо пользоваться чуть ли не всегда, ведь улучшается не только читаемость, но и надежность кода:

get '/pages/:page[Int]' => sub {
    my $page = route_parameters->get('page');
    return "Welcome to the page:$page";
};

При попытке открыть http://localhost:5000/pages/main увидим стандартную 404:

404 страница
404 страница

Если вы повторяли за мной, то уже заметили некоторое неудобство. Вносимые изменения в код не подхватываются приложением до перезагрузки сервера. Это можно исправить, добавив ключ -R с указанием директории для наблюдения при запуске:

plackup -p 5000 -R lib bin/app.psgi

Теперь при обновлении кода в директории lib сервер будет автоматически перезапущен.

Шаблоны

Шаблоны располагаются в директории views и имеют расширение .tt. Подключаются они с помощью функции template, которая первым аргументом принимает путь, а вторым переменные, которые надо ему передать:

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

Создадим views/page.tt:

<h1>Hi!</h1>
<p>You are on page: <b><% page %></b></p>

Обратиться к переданным переменным можно, используя синтаксис <% var %>.

Открываем http://localhost:5000/pages/12 и находим там:

Заметили, что на на странице имеются стили и картинки, которые мы нигде не описывали? Это базовый макет, который по дефолту создал для нас dancer2 views/layouts/main.tt. Можно его смело менять или создать свой. Только не забудьте изменить название в config.yml.

Итоги

Кажется, что информации для первой статьи более чем достаточно. Планирую продолжить серию и рассказать про: подключение к БД, выбор шаблонного движка, деплой, установку зависимостей, перенос приложения в docker. Если это вам интересно, вы знаете, что делать. Спасибо за внимание!

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

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

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

  • Часть III - работа с базой, модели и миграции

Ссылки

Комментарии (23)


  1. PrinceKorwin
    06.08.2021 15:57

    Ваш логотип прочитал сначала как Perl Danger. После прочтения статьи понял, что не ошибся.


  1. berez
    06.08.2021 19:39

    plackup -p 5000 bin/app.psgi # запускаем сервер

    А сервер при этом какой используется? Апач/нгинх или свой, перловый, дырявый?


    1. knutov
      07.08.2021 12:05

      из https://metacpan.org/dist/Plack/view/script/plackup:

      If no option is given, plackup will try to detect the best server implementation based on the environment variables as well as modules loaded by your application in %INC

      plackup - это просто запускалка. Сервер по умолчанию, в большинстве случаев - это Starman. Всего их есть много, для разных задач и на любой вкус - https://plackperl.org

      Разумеется, в продакшене перед этим следует ставить что-то типа nginx.


      1. alex_p007 Автор
        09.08.2021 18:35

        Всё правильно. Ставим перед перловым сервером nginx. Об этом расскажу в одной из слудующих частей, когда дойдем до докера.


  1. zmc
    07.08.2021 05:49

    Делал как-то sql-over-http для Oracle базы, так ни один из языков прослойки (python/php/lua) не смог отдать полностью бооольшой выхлоп от базы. Только DBI-Oracle смог справиться с этой задачей как и N-цать лет назад..


    1. PrinceKorwin
      07.08.2021 14:57

      Вообще странно. Использование курсоров, фетчинг данных пачкой и что стримить в респонз + flush - этого должно быть достаточно и доступно во всех наверное языках, кто имеет коннекторы к Ораклу.

      Разве что с их подсистемой памяти (GC) могут быть нюансы.


    1. NiceDay
      07.08.2021 22:10

      не знаю как там с другими языками, но в случае с php вам как минимум нужно

      • отключить буфферизацию в PDO (или какой там драйвер вы используете)

      • отключить буфферизацию ответа самого php (ob_... функции)

      • отключить буфферизацию сервера (например, для nginx fastcgi_buffering off;)

      вы уверены, что выполнили хотя бы эти действия?


      1. zmc
        08.08.2021 06:22

        вы уверены, что выполнили хотя бы эти действия?

        Только буферизацию nginx'а.


        Я не буду спорить в части специфики языков и тюнинга, возможно все так как Вы пишите. DBI-Oracle то же куча крутилок о назначении которых я ни чего не знаю, но он просто работает в дефолтном виде.


        1. PrinceKorwin
          08.08.2021 12:53

          Это не специфика языка, но библиотек и фреймворков. При чем здесь сам язык? :)


          1. zmc
            09.08.2021 07:11

            Да-да, язык тут не причем, а то что либа/фрэймворк пишется под язык и по стандартам языка - это не то.

            Или что, я могу взять DBD/DBI модуль работы с базой от perl'а и заюзать его в python/php, или наоборот?


  1. zmc
    07.08.2021 17:06

    Тем не менее это факт, можете сами проверить. Да и не забывайте, что Oracle сама по себе оооочень странная BD. Так что, рановато ещё perl хоронить — откапывайте.


    1. PrinceKorwin
      07.08.2021 18:23

      Здесь Oracle не причем. Дело либо в драйвере к нему, либо в клиентском коде.

      Он у вас, случайно, не остался?


      1. zmc
        08.08.2021 07:19

        Здесь Oracle не причем.

        Ни кто не утверждал что он причем. Странная СУБД Oracle - это да, но не ....

        Дело либо в драйвере к нему, либо в клиентском коде.

        Ну да, ну да. libclntsh.so во всех случаях одна и та же. Код проще некуда: connect/preparee/execute и последующий json. Но виноват кто угодно только не язык реализации коннектора.

        Из тех кто завелись с первого раза и без каких либо вопросов/твиков - это DBI-Perl и JDBC. Возиться и подкручивать что то в драйвере языка-реализации(кроме lua, с ним повозился) не было ни желания ни времени, а с java'ой я не очень дружу. Да и DBI-Oracle просто работает.

        P.S.

        Сильно разочаровал lua, так как окружение openresty, то хотелось обойтись штатными средствами, но видать не судьба.


        1. PrinceKorwin
          08.08.2021 12:56

          С первого раза завелись DBI-Perl и JDBC потому как это "тупые клиенты" к БД.

          А в Python и PHP вы использовали фреймворки поверх них с кучей функционала. И этот функционал заточен под другие основные сценарии. Тем не менее, с помощью конфигурации можно и ваш запрос реализовать.


          1. zmc
            09.08.2021 07:18

            С первого раза завелись DBI-Perl и JDBC потому как это "тупые клиенты" к БД.

            Что значит "тупые клиенты", почитайте POD по DBD/DBI, ознакомьтесь хотя бы с 10% его функционала что бы такое утверждать.

            Тем не менее, с помощью конфигурации можно и ваш запрос реализовать.

            Я не знаю какие танцы с бубном возле либы у вас практикуются, но у нас хоца что бы просто работало, а вот если где-то что-то неординарное, то можно и покрутить, но не наоборот.


            1. PrinceKorwin
              09.08.2021 11:39

              Я на DBI-Perl довольно активно лет 10 программировал если что. Знаю на сколько он "туп".

              но у нас хоца что бы просто работало

              Тогда вас стоит просто взять нужный инструмент в руки. Он есть в каждом языке :)


              1. zmc
                09.08.2021 13:22

                Я на DBI-Perl довольно активно лет 10 программировал если что

                Чет по этому поводу большие сомнения. Проверять же не будем?


                1. PrinceKorwin
                  09.08.2021 21:13

                  Вы знаете... У меня нет никакого желания откапывать эту стюардессу :) хотя в своё время было весело, да.


                  1. zmc
                    10.08.2021 10:55

                    Почему то я так и подумал ...


  1. zmc
    09.08.2021 07:17

    del


  1. kolezz
    09.08.2021 18:33

    Небольшая поправка. Книга "Learning Perl, 8th Edition" написана, отправлена в печать, но ещё не выпущена. Амазон честно пишет "This title has not yet been released"


    1. alex_p007 Автор
      09.08.2021 18:33

      спасибо! Поправил.


  1. mitya_k
    09.08.2021 18:56

    В свое время Dancer был первым моим фреймворком на Perl(а он был первым промышленным языком). Сколько воды утекло...