De la création d'une appli avec Mojolicious.
C'est plutôt le sujet de la conférence suivante, sur Lutim.
On se concentrera ici sur certains aspects qui font la force de Mojolicious.
Mojolicious n'a pas de dépendances !
(il a cependant des dépendances optionnelles : EV, IO::Socket::IP, IO::Socket::SSL)
C'est aussi un micro-framework.
(bien utile pour un prototypage rapide)
Il fournit un client et un serveur !
(on verra le détail plus loin)
Il est à la pointe de la technologie :
Mojolicious fournit mojo
, un script qui permet de :
À vrai dire… mojo
est une application Mojolicious tout comme les applis qu'on crée !
Donc certaines commandes seront obligatoirement à exécuter avec votre application.
Mais toutes sont valides avec votre application.
mojo
mojo generate <app|lite_app|makefile|plugin>
C'est le point de départ pour bosser avec Mojolicious
Cela crée la structure de votre application selon des templates fournis avec Mojolicious
$ mojo generate app Test
$ tree test
test
├── lib
│ ├── Test
│ │ └── Example.pm
│ └── Test.pm
├── log
├── public
│ └── index.html
├── script
│ └── test
├── t
│ └── basic.t
└── templates
├── example
│ └── welcome.html.ep
└── layouts
└── default.html.ep
mojo cpanify -u sri -p secr3t \
Mojolicious-Plugin-MyPlugin-0.01.tar.gz
Envoie un tarball sur le CPAN.
./myapp.pl get [OPTIONS] URL [SELECTOR|JSON-POINTER] [COMMANDS]
Avec ./myapp.pl get /
par exemple, on peut tester son appli sans la lancer ✌
Mais on peut aussi s'amuser avec des pages distantes
mojo get https://lut.im .hennypenny text
nous donne
Let's Upload That Image!
./myapp.pl inflate
Extrait les fichiers embarqués d'une application Mojolicious::Lite
$ mojo generate lite_app test
$ tree
.
└── test
$ ./test inflate
$ tree
.
├── templates
│ ├── index.html.ep
│ └── layouts
│ └── default.html.ep
└── test
./myapp.pl <daemon|prefork> [OPTIONS]
Lance l'application avec un serveur HTTP et WebSocket
(simple thread ou préforké)
./myapp.pl routes
Affiche les routes disponibles dans votre application
/perldoc/:module * perldocmodule
/ GET
./myapp.pl test
Lance les tests de votre application
Mojolicious fournit deux serveurs :
morbo myapp.pl
Codez, rechargez votre navigateur, c'est prêt !
Il n'est par contre pas fait pour la production.
Au passage : les pages d'erreur en mode development sont très bien faites et fort utiles.
Le message d'erreur et les dernières lignes de log sont présentées fort à propos.
./myapp.pl prefork
, mais optimisé pour la production ;hypnotoad myapp.pl
Plus qu'à placer un reverse-proxy devant et votre appli est en production ☺
$ hypnotoad test
$ vim test
$ hypnotoad test
Starting hot deployment for Hypnotoad server 7052.
La configuration d'hypnotoad peut être incluse dans la configuration de l'appli si on utilise les plugins Mojolicious::Plugin::Config ou Mojolicious::Plugin::JSONConfig.
On peut utiliser Mojolicious en CGI
ScriptAlias / /home/sri/myapp/script/myapp/
On peut utiliser Mojolicious en PSGI
$ plackup ./myapp.pl
HTTP::Server::PSGI: Accepting connections at http://0:5000/
Tiens, pourquoi pas un myapp.fcgi
?
#!/usr/bin/env plackup -s FCGI
use Plack::Builder;
builder {
enable 'Deflater';
require 'myapp.pl';
};
Mojolicious permet de tester simplement et rapidement son application !
Lors de la création d'une application, un répertoire t
est créé, ainsi qu'un exemple de test.
use Test::More;
use Test::Mojo;
use FindBin;
require "$FindBin::Bin/../myapp.pl";
my $t = Test::Mojo->new;
$t->get_ok('/')->status_is(200);
done_testing();
On lance alors les tests avec ./myapp.pl test
Énormément de tests sont possibles grâce à Test::Mojo.
$t = $t->content_is('working!');
En regex ce coup-ci :
$t = $t->content_like(qr/working!/);
On peut utiliser des selecteurs CSS grâce à Mojo::DOM :
$t = $t->element_exists('div.foo[x=y]');
On peut aussi tester les réponses en JSON (merci Mojo::JSON)
$t = $t->json_is({foo => [1, 2, 3]});
Ça marche aussi pour les WebSockets 😊
$t = $t->message_is('working!');
Il y a aussi les différents types de requête HTTP, bien sûr, et les tests se chaînent sans problème :
$t->post_ok('/hello.json' => json => {hello => 'world'})
->status_is(200)
->json_is({bye => 'world'});
#!/usr/bin/env perl
use Mojo::UserAgent;
use Mojo::IOLoop;
use 5.10.0;
my $delay = Mojo::IOLoop->delay(sub {
my ($delay, @titles) = @_;
say "**************";
say for @titles;
});
my $ua = Mojo::UserAgent->new;
for my $url ('https://lut.im', 'mojolicio.us', 'www.cpan.org') {
my $end = $delay->begin(0);
$ua->get($url => sub {
my ($ua, $tx) = @_;
say $tx->res->dom->at('title')->text;
$end->($tx->res->dom->at('title')->text);
});
}
$delay->wait;
$ ./test
Mojolicious - Perl real-time web framework
Lutim
The Comprehensive Perl Archive Network - www.cpan.org
**************
Lutim
Mojolicious - Perl real-time web framework
The Comprehensive Perl Archive Network - www.cpan.org
On voit bien que les réponses ne sont pas arrivées en même temps mais que le résultat est dans le bon ordre.
Les trois requêtes ont été exécutées parralèlement, accélérant grandement le temps de réponse.
Pour plus de détails sur les éléments non-bloquants de Mojolicious, voir les billets de Joel Berger sur http://blogs.perl.org
Un certain nombre de plugins sont inclus de base dans Mojolicious.
Voici mes préférés :
L'écosystème des plugins de Mojolicious est très appréciable !
http://github.com/ldidry
http://twitter.com/framasky
http://slides.fiat-tux.fr