From Sebastian Riedel

perl -Mojo -E'say g("mojolicio.us")->dom("*")->pluck("type")->uniq'

perl -Mojo -E'g("metacpan.org/search?q=mojo")->dom("big a")
->pluck("text")->join("\n")->spurt("m.txt")'

perl -Mojo -E'say g("reddit.com")->dom("*")->pluck(attrs => "href")
->grep(qr/^http/)->uniq'

perl -Mojo -E'say r g("search.twitter.com/search.json?q=perl")->json'

perl -Mojo -E'a({json => {foo => ["bar"]}})->start' get / /foo/0

perl -Mojo -E'g("mojolicio.us")->dom("h1, h2, h3")->map(sub { $_->text })
->shuffle->join("\n")->say'

mojo get www.reddit.com/r/perl/ 'p.title > a.title' text

perl -Mojo -E'say a->text_field("foo", value => "bar")'

perl -Mojo -E'a("/:name" => {inline => "Hi !"})->start' get -v /foo

perl -Mojo -E 'a(sub { shift->render(json => {time => time}) })
->start' daemon

(See mojolicio.us/perldoc/ojo for more, and also the mailing list archives.)

Advertisements

Authenticate user

From Ben van Staveren

validate_user => sub {
  my ($c, $username, $password, $extra) = (@_);

  if(MyUsers->login($username, $password) == 1) {
    return $username;
  } else {
    $c->stash(login_error_message => 'Invalid credentials');
    return undef;
  }
};

load_user => sub {
   my ($c, $uid) = (@_);

   return MyUsers->get_user_data_for_username($uid);
};

And then you want to:

my $r = $self->routes->bridge('/')->to('login#check');
$r->get('/protected')->to('....');

The 'check' method in login can simply do this:

sub check {
  my $self = shift;

  return 1 if $self->is_user_authenticated;
  $self->render('login_form') and return 0;
}

Anything now routed under $r goes through the login check. If you want "public" and "private" bits, do it like this:

my $public = $self->routes->any('/')->to('public_site#index);
my $private = $public->bridge('/')->to('login#check');

$private->get('/')->to('private_site#index');

Async page prep

From s at bykov.odessa.ua

$app->hook(
    around_dispatch => sub {
      my ($next, $c) = @_;

      # grab a title from mojolicio.us
      $c->ua->get(
        'http://mojolicio.us' => sub {
          my ($ua, $tx) = @_;

          my $res = $tx->success;
          my $mytitle = $res ? $res->dom->at("title")->text : "Error";

          # stash
          $c->stash(mytitle => $mytitle);

          # Now we are ready
          $next->();
        }
      );


    }
  );

Render pdf from memory

From Pavel Goloborodko

$self->res->headers
    ->content_disposition("attachment;filename=${name}.pdf");
$self->res->headers->content_type('application/pdf');
$self->render_data( $pdf );

When debugging code that uses attributes, as provided by Mojo::Base, it sometimes helps to visualise what its getter/setter actually looks like.

A getter/setter with defined default.

{
package MyClass;
sub my_attr {
  if (@_ == 1) {
    return $_[0]{'my_attr'} if exists $_[0]{'my_attr'};
    return $_[0]{'my_attr'} = $default->($_[0]);
  }
  $_[0]{'my_attr'} = $_[1];
  $_[0];
}
1;
}

A getter/setter without default.

{
package MyClass;
sub my_attr {
  if (@_ == 1) {
    return $_[0]{'my_attr'};
  }
  $_[0]{'my_attr'} = $_[1];
  $_[0];
}
1;
}

You can see your own attribute definitions via

export MOJO_BASE_DEBUG=1
./my_script eval 1
unset MOJO_BASE_DEBUG

A nice example of Mojolicious code as a proxy service. This is thanks to xaka at gist.


use Mojo::UserAgent;
use Mojo::Server::Daemon;

my $ua = Mojo::UserAgent->new;
my $daemon = Mojo::Server::Daemon->new(
  listen => ['https://*:443']
)->unsubscribe('request');
$daemon->on(request => sub {
  my ($daemon, $tx) = @_;

  my $req = $tx->req->clone;
  $req->url->scheme("https")->host("10.3.199.40");

  $ua->start(Mojo::Transaction::HTTP->new(req => $req) => sub {
    my ($ua, $proxy_tx) = @_;
    $tx->res($proxy_tx->res)->resume;
  });
});
$daemon->run;

If you are in the habit of setting Mojolicious environment variables in your shell, you should remember to unset them (at least MOJO_LOG_LEVEL) before upgrading your Mojolicious framework, otherwise it can fail its tests and fail to install.

unset MOJO_LOG_LEVEL
HARNESS_OPTIONS=j9 cpanm -l /srv/mojo Mojolicious Mojoliciuos::Plugin::Authentication

There are a handful of variables that can be handy when working with Mojolicious, so I decided to collect them together.

Installing CPAN modules

HARNESS_OPTIONS=j9 cpanm -l /srv/mojo Mojolicious

… specifies the degree of concurrency for the perl tests when building.

User agent

MOJO_USERAGENT_DEBUG=1 ./my_useragent.pl

… turns on debugging so it outputs request-response messages.

Daemon

MOJO_NO_IPV6=1 morbo -v -l 'http://*:8088' -w mod -w tmpl myapp

… turns off ipv6 support.

MOJO_NO_TLS=1 /srv/mojo/bin/hypnotoad myapp

… turns off TLS support.

MOJO_MODE=production …

… sets the run mode.

MOJO_LOG_LEVEL=debug …

… sets the debug level.

Commands

MOJO_NO_DETECT=1

… disables deployment environment detection.

This is one of my favourite pieces of knowledge I get to share today. Those clever people at heroku.com have made the business of publishing (modern) web applications exceedingly slick and easy. However, on the face of it (and I did hunt for a bit of time) they don’t support perl. Fret not; if you dig around under the bonnet it turns out they support any language/platform as long as someone provides a compatible ‘buildpack’. And it just so happens that Magnus Holm (a fine geek from Norway) has worked out the mechanics of getting your app publishable and provided a buildpack so it all happens behind the scenes.

(If you’re not writing your apps on Mojolicious your platform may not be modern enough — you’ll have to look at Magnus’s notes and code to see if you can become compatible. There are other buildpacks on the buildpack page.)

I will be deploying my web application from a debian server, so it made sense to create a chroot jail for it. Inside there I would be able to install third-party packages without worry of them invading my main diskspace. Wherever you deploy from, you’ll need to have root/superuser access so you can install the heroku tools.

mkdir -p /opt/jail/heroku
debootstrap squeeze /opt/jail/heroku
chroot /opt/jail/heroku
adduser --ingroup www-data --disabled-password --gecos 'app,,,' app
su - app
  • First set up your account via the web page
    • Sign up for free account
    • Give email and password
    • Acknowledge email
    • Login and go to Dev Center (for reading later)
  • Second install the heroku toolbelt
ssh-keygen
wget -qO- https://toolbelt.heroku.com/install.sh >/tmp/toolbelt.sh
view /tmp/toolbelt.sh
sh /tmp/toolbelt.sh
heroku login
heroku apps:create myapp --stack cedar \
  --buildpack http://github.com/judofyr/perloku.git

That works for debian and ubuntu — there are also installs for other platforms.
You can change the name later, but it’s slightly less trouble to get it right at the start.
(You can have multiple applications, just treat each one the same as the first.)
Application names need to be unique across heroku, so don’t be surprised if obvious names have already gone.
If you create an application without a buildpack (as I did) don’t worry, you can add a buildpack with

heroku config:add BUILDPACK_URL=http://github.com/judofyr/perloku.git
  • Third set up your development directory
    • Create a directory [in fact I created a chroot jail and a special user but that’s only if you want complete isolation] and go into it
mkdir myapp
cd myapp
git init
vi Perloku ...
git add .
git commit -m 'Initial'
git push heroku master
  • Fifth try out your new application

Referenced links