Get Firefox 2
Mojolicious and sprintf loggin
February 27th, 2013 :: Permalink

Don’t want to write things like

app->log->debug("foo $config->{foo} versus ".stat->mtime." seconds");

but rather

app->log->debug("foo %s versus %d seconds", $config->{foo}, stat->mtime);

but Mojo::Log does not support that directly. You could use this:

app->log->debug(sprintf("foo %s  versus %d seconds", $config->{foo}, stat->mtime));

with the downside that sprintf() is called even if the message would not be logged due to your app’s log level being higher than that of the call.

Alternatively you could base your own logger class on Mojo::Log:

#!/usr/bin/perl

package My::Log;
use base Mojo::Log;

sub format {
        my ($self, $level, $format, @parameters) = @_;

        return $self->SUPER::format($level, sprintf($format, @parameters));
};

package main;

use Mojolicious::Lite;

app->log->error("this string %s printf %s", 'uses', 'stuff');
app->log->warn('decimal: %d hex: %x', 16, 16);
app->log->info('pi: %.2f', 3.14159265359);

And it’s output:

[Wed Feb 27 17:24:34 2013] [error] this string uses printf stuff
[Wed Feb 27 17:24:34 2013] [warn] decimal: 16 hex: 10
[Wed Feb 27 17:24:34 2013] [info] pi: 3.14
by bd in Mojolicious
  Comments Off

Mojolicious behind Apache with mod_proxy
February 27th, 2013 :: Permalink

This is the only way I got an Mojolicious application to work behind an apache2 web server using mod_proxy.

Setting the base will make sure that your routes match the incoming URLs and that the right URL is used in redirects:

my $base = 'http://localhost:3000/app1';

hook 'before_dispatch' => sub {
        shift->req->url->base(Mojo::URL->new($base));
};

When using the style sheet or JavaScript helper a leading slash is important, else the path will be wrong:

%= stylesheet '/css/foo.css'

And this is the apache config snippet:

ProxyPass /app1 http://localhost:3000
ProxyPassReverse /app1 http://localhost:3000/app1

Note the missing /app1 at the end of the ProxyPass line.

The complete Mojolicious code:

#!/usr/bin/env perl
use Mojolicious::Lite;

use Time::HiRes qw/gettimeofday/;

my $base = 'http://localhost:3000/app1';

hook 'before_dispatch' => sub {
        shift->req->url->base(Mojo::URL->new($base));
};

under sub {
        shift->stash(now => join('.', gettimeofday()));
};

get '/' => sub {
        my $self = shift;
        $self->render('index');
} => 'index';

get '/foo' => sub {
        my $self = shift;
        $self->render('foo');
};

get '/redirect' => sub {
        my $self = shift;
        $self->redirect_to('foo');
};
 app->start;

__DATA__

@@ foo.html.ep
% layout 'default';
% title 'Foo';

@@ index.html.ep
% layout 'default';
% title 'index';

@@ layouts/default.html.ep
<!DOCTYPE html>
<html>
  <head>
    %= stylesheet '/css/foo.css'
    <title><%= title %></title>
  </head>
  <body>
    <h1>Welcome to <%= title %></h1>
    <p>Now: <%= stash('now') %></p>
    <%= content %>
    <hr/>
    <ul>
     <li><%= link_to 'Index' => 'index' %></li>
     <li><%= link_to 'Foo' => 'foo' %></li>
     <li><%= link_to 'Redirect' => 'redirect' %>: Will redirect to foo</li>
    </ul>
  </body>
</html>

 

by bd in Mojolicious
  Comments Off

Mojolicious and Linux::Inotify2
February 26th, 2013 :: Permalink

This is a tiny example on how to use Linux::Inotify2 from within a Mojolicious application to watch a file for modification. Note: this will not work with morbo, as no inotify will be delivered to the app. Update: it works with morbo if you use our $io = … instead of my $io = …. The reason for that is, my $io goes out of scope as app->start() does not block.

You will need these modules:

  • Linux::Inotify2 - scalable directory/file change notification
  • EV – perl interface to libev, a high performance full-featured event loop
  • AnyEvent – the DBI of event loop programming
  • And of course Mojolicious

Steps to see the magic happen:

  1. Save the code below to /tmp/i.pl
  2. Create file to be watched: touch /tmp/foo
  3. Run your app (again, morbo will not work): /tmp/i.pl daemon
  4. In another shell, update the watched file: touch /tmp/foo

This is what Mojolicious should log:

[Tue Feb 26 21:22:09 2013] [info] Listening at “http://*:3000″.
Server available at http://127.0.0.1:3000.
[Tue Feb 26 21:22:13 2013] [debug] file changed
[Tue Feb 26 21:22:13 2013] [debug] file changed
[Tue Feb 26 21:22:13 2013] [debug] file changed

Code:

#!/usr/bin/perl

use Mojolicious::Lite;

use Linux::Inotify2;
use EV;
use AnyEvent;

sub file_changed {
        app->log->debug("file changed");
}

sub setup_notify {
        my $inotify = new Linux::Inotify2;
        $inotify->watch('/tmp/foo', IN_ALL_EVENTS, 
                \&file_changed);

        my $io = AnyEvent->io(
                fh => $inotify->{fd},
                poll => 'r',
                cb => sub { $inotify->poll }
        );

        return $io;
}

get '/' => sub { shift->render_text('index') };

our $io = setup_notify();

app->start();
by bd in Mojolicious
  Comments Off

Too Cool for Internet Explorer