Показаны сообщения с ярлыком CPAN. Показать все сообщения
Показаны сообщения с ярлыком CPAN. Показать все сообщения

суббота, 19 мая 2012 г.

Try::Tiny и диспетчеризация исключений

Проблема 
Многие используют Try::Tiny. Все в этом модуле хорошо, только не хватает вот чего-то вроде:
try {
   die Class1->new();
}
catch('Class1') {
   # Catch all exceptions of Class1
}
catch('Class2') {
   # Catch all exceptions of Class2
}
catch {
   # Catch other exceptions
}
К сожалению, сделать такой синтаксис, не убрав "::Tiny" с названия модуля, не так просто. Кроме того, переписывать Try::Tiny вообще нет никакого желания.

Решение 1
Немного подумав я пришел к такому варианту:

вторник, 15 мая 2012 г.

Mojolicious::Plugin::RenderFile для отдачи файлов

Стояла задача дать пользователю возможность скачать файл. Покопавшись в документации, я нашел 2 варианта - хелперы "render_data" и "render_static". Оба варианта мне не подошли. 
"render_data" - принимает строку, а я не хотел вычитывать весь файл в память.
"render_static" - отдает файлы с "public" директории.

render_file 
Интернет предложил различные варианты решения проблемы, но какого-то удобного я не нашел, решил написать свой хелпер. Хелпер должен был уметь отдавать файл по абсолютному пути с любой папки без вычитывания файла в память, и чтобы браузер предлагал пользователю файл сохранить, а не пытался рендерить. Так появился "render_file". Используется он так:
# Provide any file name
$self->render_file(
    filepath => '/tmp/files/file.pdf',  
    filename => 'report.pdf'
);

пятница, 13 января 2012 г.

Валидация данных в Mojolicious

Написал небольшой плагин для Mojolicious  - Mojolicious::Plugin::ValidateTiny. По сути - это обертка над Validate::Tiny с дополнительными удобными плюшками.

Для валидации входящий параметров мы просто используем хелпер:
$self->do_validation($validate_rules);
$validate_rules - это описание проверок в формате Validate::Tiny.

По-умолчанию, включена опция "autofields", которая позволяет использовать сокращенный вариант правил проверки. И вместо:
  {  
     fields => ['user', 'pass'],
     checks => [user => is_required(), pass => is_required()] 
  }
можно писать:
 [ user => is_required(), pass => is_required() ]
и fields автоматически заполнятся исходя из описания проверок.

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

Кроме хелпера "validator_error", есть еще хелпер "validator_any_error".
  my $errors     = $self->validator_error;         # hashref with errors
  my $pass_error = $self->validator_error('pass'); # password error text
  my $any_error  = $self->validator_any_error;     # any error

четверг, 5 января 2012 г.

Быстрая установка зависимостей Perl-приложения

Имеется приложение на Perl, которое имеет множество зависимостей. Задача - упростить установку зависимостей такого приложения.
Есть несколько подходов к решению данной задачи, но я расскажу лишь про тот вариант, который я использую и он мне нравится больше всего.

 Все модули я ставлю с CPAN в локальную директорию пользователя, использую для этого "local::lib".

Предварительно необходимо описать все зависимости приложения в Makefile.PL. Например, файл может выглядеть вот так:

Процедура установки:
  1. Копируем код приложения на чистый сервер.
  2. Устанавливаем и настраиваем "local::lib" (инструкция)
  3. Устанавливаем "App::cpanminus" в локальную директорию ( возможно придется установить вручную - make, make test, make install ).
  4. Переходим в папку с приложением и выполняем команду - "cpanm --installdeps ." и ждем пока установятся все зависимости.
Вот так все просто и быстро :)

вторник, 8 ноября 2011 г.

Mojlicious: Использование роутов в javascript

Мне нравится, как реализованы роуты в Mojolicious и особенно мне нравится то, что их можно именовать. Именую я роуты всегда в соответствии с именем контроллера и метода.
Например,
$r->get('/messages/:id')->to('messages#show')->name('messages_show');
$r->post('/messages/:id/delete')->to('messages#delete')->name('messages_delete');
И затем в контроллере:
$self->redirect_to('messages_show', id =>123);
Такой подход позволяет изменять роуты с меньшим влиянием на остальной код. И все бы хорошо, но часто приходится использовать роуты не только на стороне сервера, но и на стороне клиента. Например,
var some_id = 123;
$.getJSON('/messages/' + some_id, function(data){ ... });
$.post('/messages/' + some_id + '/delete', function(data){ ... });
Хотелось бы иметь возможность использовать имена роутов и на клиентской стороне. Для этой задачи и был написан плагин "Mojolicious::Plugin::JSUrlFor". Достаточно добавить в основной ваш лейаут:
<%= js_url_for %>
и в клиентском javascript-е будет доступна функция "url_for"( аналогична хелперу "url_for" с "Mojolicious::Plugin::DefaultHelpers"):
var some_id = 123;
$.getJSON( url_for('messages_show', {id:some_id}), function(data){  } );
$.post( url_for('messages_delete', {id:some_id}), function(data){  } );
Модуль "Mojolicious::Plugin::JSUrlFor" пока еще только на Github, но заброшу на CPAN сразу, как покрою тестами.

вторник, 1 ноября 2011 г.

Mojolicious и защита от Cross Site Request Forgery (CSRF)

Немного теории
Я полагаю многие знают, что такое CSRF. Но для новичков озвучу. CSRF (Cross Site Request Forgery) - это межсайтовая подделка запросов. И происходит она следующим образом.

Допустим, на вашем сайте, назовем его "mysite.com", есть ссылка, которая удаляет сообщение. Ссылка вида - "http://mysite.com/myprofile/delete?message=123".

Злоумышленник может вставить эту ссылку на свой сайт "attackerssite.com", например,  в виде картинки -
<img src="http://mysite.com/delete?message=123" />
И если Вы зайдете на "attackerssite.com", то будет отправлен запрос на загрузку картинки с вашего сайта, но вместо загрузки картинки будет удалено сообщение. Проблем с авторизацией не будет, так как будет отправлена ваша кука, запрос же отправляется с вашего браузера.

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

среда, 26 октября 2011 г.

Интересности Perl

Как-то совсем давно я ничего не писал, думаю уже пора :). Не так давно прошла конференция BlackPerl 2011. Я думаю, что уже многие в курсе относительного этого события.
Я на конференцию ехал без доклада, просто с желанием познакомится с Perl-комьюнити, послушать других и пофотографировать сие действо. Но вдохновленный докладчиками, решил и сам соорудить небольшое выступление. Поскольку, конкретной темы у меня не было, я решил просто рассказать про интересные вещи в Perl. Ничего особенного, но возможно кто-то найдет для себя что-то новое.

Приступим.

Приватные методы
В Perl возможно реализовать приватные методы и делается это следующим образом:

Недостаток такого подхода в том, что caller будет нам возвращать "__ANON__" в качестве имени нашего метода. И stack trace будет нечитабельным.


четверг, 23 июня 2011 г.

Запускаем Mojolicious/PSGI приложение: мини-тест производительности.

Решил провести небольшое тестирование производительности Mojolicious  в разных режимах:
  1. Mojo::Server::Daemon (Epoll/Poll)
  2. Mojo::Server::Hypnotoad (Epoll/Poll)
  3. Mojo::Server::PSGI + Corona
  4. Mojo::Server::PSGI + Starman
  5. Mojo::Server::PSGI + Starlet
  6. Mojo::Server::PSGI + Plack::FCGI::Handler
Хотелось еще протестировать nginx+uwsgi, но не сложилось. Возможно в следующий раз.


Как проводилось тестирование 
Тестировалось приложение, которое просто возвращает строку "OK". Также, в тех же условиях, тестировалось минимальное PSGI приложение. Основной задачей было узнать наиболее производительный режим запуска. 
Все запросы к приложению проксировались через nginx - 4 воркера по 1024 конекшенов максимум. Тестировалось при помощи утилиты "ab". Результат считался как среднее арифметическое по 3 запускам теста. 10000 запросов на тест.

пятница, 27 мая 2011 г.

Развертываем Perl приложение на DotCloud

Немного про PSGI
Спецификация PSGI стала очень важным(переломным) моментом в мире разработки Perl веб-приложений. По сути, произошло отделение протокола взаимодействия с веб-сервером от API фреймворка, что позволило запускать PSGI приложения в любом окружении(возможно стоит про это написать отдельный пост :) ). Все современные фреймворки поддерживают PSGI.

Как выглядит PSGI приложение?
PSGI приложение это просто ссылка на функцию. Эта функция принимает ссылку на хеш с описанием окружения и возращает ссылку на массив с трех элементов(статус, хидеры, боди)
sub app {
    my $env = shift;
    return [
        '200', 
        [ 'Content-Type' => 'text/plain' ],
        [ "Hello World" ], # or IO::Handle-like object
    ];
}

Если хотите попробовать, то установите себе Plack c cpan и запустите:
plackup  -e 'sub {my $env=shift; return [200, [Content-Type => "text/plain"], ["Welcome home, $env->{QUERY_STRING}"]] }'
Затем откройте в браузере http://localhost:5000/?Dude

Приложения на базе Mojolicious и Dancer  умеют работают в режиме PSGI.

Теперь ближе к сабжу - разворачиваем наше приложение
Dotcloud - это платформа для развертывания ваших приложений. C Dotcloud Вы можете забыть про настройку веб-сервера. Просто выполняем "dotcloud deploy myapp" и приложение готово к использованию :). Для примера,  возьмем приложение c поста - "Пример приложения на Mojolicious ( не Lite )". ( Предварительно необходимо завести себе аккаунт на dotcloud.com и установить клиент - sudo easy_install dotcloud. )

четверг, 26 мая 2011 г.

Mojo::JSON для сессий в Mojolicious

Сейчас Mojolicious использует Storable для сериализации сессий, но Себастьян решил перейти на Mojo::JSON и мне нравится эта идея :). Я приверженец формата JSON и уже упоминал его преимущества в посте "Как устроены сессии в Mojolicious?!". Проблемы могут возникнуть только у пользователей, которые хранят в сессии блесснутые(blessed) ссылки.

Тикет с обсуждением на гитхабе.

пятница, 15 апреля 2011 г.

Mojolicious 1.16: Экстренный релиз, Всем обновляться!!!

Час назад стало известно про серьезную уязвимость в Mojolicious, которая позволяет вычитать любой файл с файловой системы.
Баг уже исправлен, к сожалению баг был опубликовал в твиттере перед тем как передан Себастьяну.
Все срочно обновляемся!!!! Но учтите, что новый релиз не сразу попадет на все зеркала CPAN, лучше качайте прямо с официального сайта.

Если обновление слишком накладно, то настройте веб сервер, чтобы он пропускал только валидные роуты.

Дополнительная информация:

понедельник, 28 марта 2011 г.

Mojoliciuos - Производительность Mojo::JSON

Mojo::JSON VS JSON::PP
Решил проверить производительность Mojo::JSON
Интересовала, естественно, производительность в сравнении с JSON::PP.
Колоссальная производительность JSON::XS лишает смысла сравнивать его с перловыми реализациями.

Результаты
Тестирование показало, что Mojo::JSON в 1.5 раза быстрее чем JSON::PP при сериализации и в почти в 3 раза быстрее при десериализации. Очень даже неплохо.
Естественно, JSON::XS вне конкуренции, он в 40 раз быстрее чем Mojo::JSON при сериализации и в 30 раз быстрее при десериализации.

Если мы посмотрим на абсолютные цифры производительности Mojo::JSON, то 3-5 тыс вызовов в секунду хватит для большинства проектов. Кроме того, в тесте использовалась достаточно сложная структура данных.  Ну и всегда можно переключится на JSON::XS

вторник, 22 марта 2011 г.

Guttman-Rosler Transform. Часть 1: Описание преобразования.

Уже наверное больше года хочу написать про GRT(Guttman-Rosler Transform) и наконец-то дошли руки. Вернее, наткнулся на Sort::External::Cookbook, который и взял за основу своего поста. Повествование решил разбить на две части. Первая с описанием, вторая с результатами тестирования.

Собственно сабж.
Думаю многие знакомы с преобразованием Шварца, которое позволяет повысить эфективность сортировки за счет предварительной подготовки сортируемых данных. Преобразование Гутмана-Рослера это еще один способ повышения эфективности сортировки.

Perl имеет очень удобную в использовании функцию sort. Когда мы хотим нестандартный порядок сортировки, то мы использует колбек, который передаем в функцию sort.
Например, sort {$b <=> $a } @array;

Идея GRT заключается в том, чтобы преобразовать входные данные так, чтобы мы могли сортировать без использования дополнительного колбека( "sort @transformed_array;" )

Тогда вся сортировка будет происходить на уровне C, что даст нам выигрышь в скорости.

воскресенье, 27 февраля 2011 г.

Встречайте Mojolicious::Plugin::Gravatar

Написал небольшой плагин для Mojolicious - Mojolicious::Plugin::Gravatar . Добавляет хелперы для работы с Gravatar.com.  Думаю многие знакомы с этим сервисом( его используют cpan и github ), но кто не знаком - обратите внимание.

Для отображения аватарки  - <%= gravatar $email %>
Для получения url аватарки - <%= gravatar_url $email %>

Плагин уже на GitHub и на CPAN 

понедельник, 21 февраля 2011 г.

Mojolicious - интервью с Себастьяном Риделем( Sebastian Riedel )

Мой перевод интервью ActiveState с Себастьяном Риделем( Sebastian Riedel ), создателем веб-фреймворка Mojolicious. Это достаточно свободный перевод, но я старался не потерять суть.

14.02.2011 Себаcтьян зарелизил Mojolicious 1.1 - Perl веб-фреймворк следующего поколения. В связи с этим и состоялось интервью.

Tara: Почему ты занялся созданием Mojolicious?

Sebastian: По большому счету это случилось случайно. Стартовал Mojolicious в конце 2008 под названием Mojo, как фреймворк для  разработчиков веб-фреймворков. Он должен был решить многие проблемы архитектуры Catalyst и подразумевался как замена для его устаревающих внутренностей. Но когда текущие мейнтейнеры Catalyst отказались от использования Mojo, то я решил показать его ценность, создав но его основе пример  веб-фреймворка.
Затем этот пример под названием Mojolicious превысил все ожидания, и я никогда не пожалел о случившемся.

Tara: Какие уроки приобретенные во время работы над Catalyst, оказались полезными при создании Mojolicious?

Sebastian: Я полагаю, что наиболее важным уроком, который я выучил, было искусство построения сообщества. Активное сообщество является наиболее ценным активом для любого фреймворка и является основной его популярности. И хотя  Mojolicious очень молодой проект, но у нас уже второе по размеру сообщество среди всех веб-фреймворков на Perl, мы идем сразу за Catalyst.

Tara: Есть ли какие-то примеры действующий проектов на Mojolicious? Какого рода проекты создаются при помощи Mojolicious?

воскресенье, 20 февраля 2011 г.

Как устроены сессии в Mojolicious?!

В этом посте я не буду рассказывать про API для работы с сессиями, это можно найти в документации к Mojolicious, а постараюсь объяснить как устроены сессии внутри.

Mojolicious использует сookies для хранения сессий. И это достаточно важный момент. Такой подход позволяет нам следовать REST идеологии. Мы можем отказаться от лишних состояний на стороне сервера, нам не нужно обеспечивать общего пространства для доступа к сессиям с разных серверов.

Но имеется несколько важных нюансов:
  1. Старайтесь не делать сессии большими, поскольку эти данные будут передаваться при каждом запросе, а максимально безопасный размер cookie - 4кб.
  2. Вопрос авторства данных.
С первым пунктом все ясно, а относительно второго, то это решается либо шифрованием либо подписью cookies. Mojolicious использует подписанные(signed) cookies.

Что должна обеспечивать подпись?
Начнем с того, что любая подпись (включая подпись ручкой на бумаге) должна обеспечить следующие две вещи:
  1. Идентифицировать автора подписи.
  2. Гарантировать, что после того, как документ подписали, он не изменялся.
Подписанный документ не подразумевает того, что он должен быть зашифрован. Соответственно подписанные cookies не обязаны быть зашифрованными.
Мы оставляем документ в открытом виде и лишь добавляем к нему подпись(цифровую или ручкой на бумаге)

среда, 1 декабря 2010 г.

Чем плох eval?!

Чем плох eval?!
В perl, как всем известно, имеется 2 варианта вызова функции eval. Строковый eval для компиляции и выполнения кода на лету и блочный eval.
Нас интересует блочный eval.
Часто встречается такой вот код:


eval { 
  # some code 
  die "error"; 
  # some code  
}; 

if ($@) { 
    print "Error [$@] occured!"; 
}

Это вполне стандартный код, но есть ряд недостатков связанных и с использованием глобальной переменной $@.
Потенциальная проблема #1
Если кто-то локализировал переменную $@, то мы не сможем перехватить исключение. В этом коде мы не видим ошибки.


sub do_die { 
    die "Error"; 
} 

eval { 
    local $@;
    do_die(); 
}; 

if ($@) { 
    print "Error [$@] Occured!"; 
} 


Потенциальная проблема #2
Если в деструкторе используется eval, то скорее всего мы не перехватим исключение. Пример:

package Object;
sub new { 
    my $class = shift; 
    my $self  = {}; 
    bless $self, $class; 
}

sub DESTROY {
    eval { 
        # some clean code 
    } 
} 

package main; 
eval { 
    my $obj = Object->new(); 
    die  "Error"; 
}; 

if ($@) { 
    print "Error [$@] Occured!";
} 

  Деструктор с eval-ом может быть в ком-то модуле с CPANа и Вы просто не будете знать про это.
Потенциальная проблема #3
 $@ может содержать объект, которые в булевом контексте вернет ложь.

Решение
В связи со всем вышесказанным, рекомендую использовать  модуль Try::Tiny либо TryCatch. Они позволят Вам  избежать описанных проблем в будущем  и предоставят удобные и понятные синтаксический конструкции(try{}catch{} finally{}).  

Я использую Try::Tiny, он мне нравится своей минималистичностью и отсутствием внешних зависимостей. 

Вот пример кода с Try::Tiny. Красиво и надежно :).
# handle errors with a catch handler
try {
    die "foo";
}
catch {
    warn "caught error: $_";    # not $@
};

# just silence errors
try {
    die "foo";
};
Более доходчиво про это все написано в "perldoc Try::Tiny".

понедельник, 30 августа 2010 г.

CPANPLUS и Gentoo - Автоматически создаем ebuild-ы модулей из CPAN

Часто встречается такая ситуация, что в системе часть модулей инсталлировано через пакетный менеджер, а часть через cpan. Потом это приводит к разного рода проблемам связанные с тем, что пакетный менеджер не видит модули установленные через cpan.

1. Пакетный менеджер тянет по зависимостям уже установленный через cpan модуль.
2. Удаление через модулей через пакетный менеджер также не учитывает зависимости.

3. При обновлении Perl до новой версии невозможно обновить все модули через perl-cleaner.
4. ... и так далее



Решение очевидное - устанавливать все через пакетный менеджер. А если нет нужного пакета(в Gentoo - это еbuild-ы), то создавать самому.
Есть такая тулзень - "g-cpan", предназначенная для этих целей. Но у нее был ряд проблем( криво как-то работала с CPAN-репозитариями ). Возможно в новых версиях все уже исправлено.

Но сегодня мы говорим про другой инструмент, а именно про CPANPLUS. Многие уже наверное давно его оценили и пользуются командой "cpanp" вместо "cpan". 
Я же предлагаю пользоваться еще одной командой входящей в состав CPANPLUS - "cpan2dist"
Выполняем "cpan2dist --help" и смотрем для начала секцию "Examples". Как видим, мы может создавать не только ebuild-ы, но пакете в других форматах, включая deb.
Для установки Mojolicious выполняем:


cpan2dist --format=CPANPLUS::Dist::Gentoo \
--dist-opts overlay=/usr/local/portage \
--dist-opts distdir=/usr/portage/distfiles \
--dist-opts manifest=yes \
--dist-opts header="# Copyright 1999-2010 Gentoo Foundation" \
--dist-opts footer="# End" \
--ignore Data::Dumper
Mojolicious

Мы игнорируем Data::Dumper поскольку для него нет отдельного ebuild-а в системе, а он нужен по завимостям.

Пакет попадает в оверлей "/usr/local/portage". На него должна указывать переменная в файле /etc/make.conf
PORTDIR_OVERLAY="/usr/local/portage"

Теперь можем устанавливать пакет: emerge -av perl-gcpanp/Mojolicious. Возможно перед установкой придется размаскировать пакет.



Вот и все.


суббота, 17 апреля 2010 г.

Экономия памяти: YAML::Tiny

Небольшое вступление для тех, кто  еще не использует YAML (позволю себе процитировать википедию )
YAML — человекочитаемый формат сериализации данных, концептуально близкий к языкам разметки, но ориентированный на удобство ввода-вывода типичных структур данныхмногих языков программирования. 
Я использую YAML для разного рода конфигурационной информации.
Почему я использую YAML? :
  • YAML краток и понятен;
  • YAML очень выразительный и расширяемый;
  • YAML допускает простой потоковый интерфейс;
  • YAML использует структуры данных, родные для языков программирования;
  • YAML легко реализуется, возможно, слишком легко;
  • YAML использует цельную модель данных. Нет исключений — нет беспорядка.
Сабж
Идея YAML::Tiny - Читать/Писать  YAML данные с минимальными затратами + минимум внешних зависимостей(не использует ничего, кроме стандартных модулей). 
Просто заменив в коде:
use YAML 'LoadFile';
на 
use YAML::Tiny 'LoadFile'; 
я сэкономил 4МБ памяти в каждом FCGI процессе!!!

Спецификация YAML невероятно огромна.  И Pure Perl реализация - модуль  YAML поддерживает ее полностью и съедает 4МБ оперативной памяти. Yaml::Tiny мал и быстр за счет того, что он не поддерживает все возможности описанные в спецификации.  

ЗЫ: Если не хватает возможностей YAML::Tiny, тогда следует смотреть в сторону YAML::Syck


вторник, 16 марта 2010 г.

Обновил Debug::LTrace до 0.02

* Обновилась документации и тесты.
* Теперь модуль без проблем инсталлируется под 5.8.x

ЗЫ: Как приятно смотреть на все эти зелененькие "PASS" в CPAN Testers Report :))