воскресенье, 27 июля 2014 г.

Фотографии с Perl-хакатона в Киеве (2014)

В Киеве 19-20 июля 2014  прошел Perl-хакатон. Мероприятие посетил Марк Леманн - автор AnyEvent, Core, JSON::XS и libev. Думаю, многие слашали про node.js, но мало кто знает, что в нем по-началу использовался libev.

Хакатон прошел в дружественной атмосфере, vti подобрал хорошее место для мероприятия и было, как говорится, уютно и комфортно. Единственное, чего мне хватило, так это кофе. Нет кофе брейк был, но представь себе ситуацию, ты выходишь на кофе-брейк, там печеньки, кофе, общение - все прекрасно. Затем ты идешь в основную комнату и отчаянно пишешь код, делаешь паузу, идеш опять к печенькам и кофе, а там... все убрали и пусто... шок и разачорование. А программист - это машина, которая перерабатывает кофе в код. :) В остальном все было отлично. В детали вдаваться не буду, это был классический хакатон: мини-проекты, команды, презентация результатов, общение, посиделки в пабе.

Собственно сабж:



суббота, 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'
);

понедельник, 14 мая 2012 г.

Немного фотографий с Perl Mova 2012


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


Собственно фотки

 


вторник, 17 апреля 2012 г.

Посещение iforum

Сегодня я со своими орлами посетил в очередной раз iforum. В этот году, если я не ошибаюсь, зарегистрировалось более 4 тыс. человек. Мероприятие - про бизнес, рекламу, продвижение, технологии в Интернет.  Изначально, я собирался посетить техническую секцию доклады Дмитрия Сатина.  Техническую секцию конечно сложно назвать откровением, но было вполне неплохо с расчета на массовую аудиторию. На докладах Дмитрия, как всегда, не было где яблоку упасть.

И парочка фотографий ...

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


пятница, 17 февраля 2012 г.

Первая техническая втреча Kiev.pm

16 Февраля 2012 года, в 19:30 в помещении GL Club, Киев состоялась техническая встреча Kiev.pm - группы пользователей Perl. Посетило встречу около 12 человек. Провели 2 доклада, на остальные не хватило времени и решили перенести на следующий раз.

Доклады:
  1. "Nginx. По следам мастер-класса Игоря Сысоева" Денис Жданов. Презентация 
  2. "Redis. Protocol::Redis"  Сергей Засенко. Презентация





пятница, 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 г.

Теперь постом можно поделиться в социальных сетях

Я наконец-то добавил кнопки публикации информации про пост в социальных сетах. Пришлось немного порыться в интернетах, а то у меня используется нестандартный шаблон для блога и блогспот не мог к нему автоматически добавить эти кнопочки. Теперь можно поставить +1 любому понравившемуся посту. Пользуемся, не стесняемся ;).

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 будет нечитабельным.


вторник, 9 августа 2011 г.

IGAL - создаем фотогалерею за 5 минут

У меня стояла задача раздать всем фотки после праздника. Логичнее всего раздать их через интернет. Следовательно возникли следующие требования:

  1. Фотографии должны быть доступны для скачивание только определенному кругу людей.
  2. Фотографии должны быть доступны в полном размере( не ужатые )
  3. Должна быть возможность предварительного просмотра фотографий.
  4. Должна быть возможность пакетного скачивания фотографий.

Фотографий всего было где-то около 10 гб. Подходящего веб-сервиса я не нашел и решил создать самому веб-галерею и залить ее на свой сервак. После недолгих поисков я нашел очень удобный скрипт (написан на Perl) для генерации статической фото-галереи из папки с фотками.

Скрипт называется igal ( http://igal.trexler.at/ ). Все что нужно - это просто запустить его в нужной папке. Результат будет выглядеть примерно так - http://igal.trexler.at/igal2-sample/.

Я использовал опцию "-s make no HTML slides, link thumbnails to images", чтобы превьюшки ссылались сразу на JPG файлы.

Для ограничения доступа настроил аутентификацию в nginx, а для пакетного скачивания можно использовать менеджер закачек типа DownloadMaster( умеет скачивать все линки со страницы).

пятница, 1 июля 2011 г.

Тест на понимание Perl: Вопрос 5

Вопрос
Что выведет следующий код?
$MODE = 'debug';

sub is_debug { $MODE =~ /debug/gi ? 1:0 }

print 5 if is_debug();
print 6 if is_debug();
print 7 if is_debug();
Ответ: 57


Пояснение
Вызов функции is_debug будет нам по очереди возвращать то 1, то 0. Это связано с тем, что мы используем регексп с модификатором "g" в скалярном контексте. В такой ситуации при удачном совпадении Perl запоминает позицию на которой остановился и в следующий раз продолжает поиск с нее.

Нужно такое поведение, для таких вот ситуаций:
$x = "cat dog house";
while ($x =~ /(\w+)/g) {
    print "Word is $1, ends at position ", pos $x, "\n";
}

Детали в perldoc perlretut

среда, 29 июня 2011 г.

Ищем Perl-программистов в Киеве и Чернигове (Украина)

Для Perl программистов есть 2 вакансии - одна в Киеве и одна в Чернигове.

Компания Portaone.
Описание киевской вакансии -  http://www.portaone.com/company/careers/developer/
Описание черниговской вакансии -  http://www.portaone.com/company/careers/web-developer/

Работать будете в команде профессионалов, начинающих программистов в компании практически нет.

Если что-то интересует - спрашивайте, постараюсь ответить на все вопросы.

четверг, 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 запросов на тест.

понедельник, 6 июня 2011 г.

Наконец-то исправлена обработка исключений в Perl 5.14

Все уже знают про выход Perl 5.14, но почему везде пишут лишь про новые плюшки?! Но то что была наконец-то решена древняя проблема с обработкой исключений, никто и не вспоминает.

В Perl мы используем die для генерации исключения и блочный eval для перехвата. Конструкция, думаю, знакома всем:
eval { 
  # some code 
  die "error"; 
  # some code  
}; 

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

Так вот, кроме того, что это выглядит коряво, так это еще и работает(до версии 5.14) не всегда хорошо. Проблема описана в моем посте "Чем плох eval?!"

В perl 5.14 произошли изменения в поведении die, warn и $@, что решило проблемы описанные в вышеупомянутом посте. Теперь можно не боятся, что деструктор затрет исключение.  Также  local $@ не испортит нам жизнь.

Более детально читайте в perldoc perldelta => Exception Handling.

Можно было бы отказаться и от Try::Tiny, но есть еще эстетические соображения :)

пятница, 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) ссылки.

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

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

Конвертируем HTML в PDF

Предыстория
Есть некое веб-приложение(на Perl), в котором нужно было добавить определенный набор отчетов. Отчеты должны иметь два представления - HTML и PDF.

Для решения этой задачи, естественно, можно было бы воспользоваться модулями типа PDF::Reuse, PDF::API2, PDF::API2::Simple, но:
1. Это лишние временные затраты (изучение API, написания дополнительного кода)
2. Это усложнение сопровождения отчетов. Необходимо дублировать логику HTML-шаблонов в PDF и постоянно поддерживать это в актуальном состоянии.

Поэтому, было выбрано другое решение - использовать конвертор HTML в PDF. Сразу оговорюсь, что было это года 3-4 назад. Для PHP, вроде как, на то время уже существовал dompdf(рендеринг написан на php), а для Perl ничего такого не было.

Провал HTMLDOC
После долгих поисков нашел такую тулзень как HTMLDOC. Но она была далеко не идеальна:
1. В HTMLDOC нет поддержки Unicode, поэтому приходилось предварительно перекодировать HTML в cp1251.
2. Шрифты, которые идут с HTMLDOC не поддерживают кириллических символов. Но в интернетах был найдет комплект шрифтов с поддержкой кириллицы. Главное после установки HTMLDOC не забыть заменить шрифты :)
3. Поддержка только базового HTML(про CSS забудьте). Пришлось довольствоваться чем было.

В добавок на прошлой неделе мне пришли жалобы, что в отчетах съедаются диактрические символы(типа всякие умляуты в немецком и так далее) и я начал искать решение.

Первой попыткой было использовать  HTMLDOC 1.9 (нестабильный релиз),  там добавили базовую поддержку Unicode. После 8-го segfault с 10 попыток конвертации, было решено вернуться к предыдущей версии(без поддержки  Unicode)

Вторая попытка была заменять не CP1251 символы на escape-последовательности вида "&#xxxx;", но после 3-4 последовательностей в файле, HTMLDOC их просто переставал преобразовывать в нужные символы.

Триумф WKHTMLTOPDF
Я начал искать новый конвертор. И каково было ж мое удивление, когда я нашел такого зверя, как  WKHTMLTOPDF :)

WKHTMLTOPDF - это консольный конвертор, который использует Webkit для рендеринга HTML, следовательно PDF документы будут максимально приближены к оригинальному HTML. И это реально так, можете смело использовать CSS-стили. WKHTMLTOPDF сконвертит HTML практически любой сложности!!!