Web Development
42.1 PSGI/Plack: The Foundation
Plack middleware: Plack::Builder (enable 'Session'; enable 'Static', path => qr{^/static}), access logs, CORS, auth, compression. Servers: Starman, Starlet, Gazelle, Twiggy (async), uWSGI.
# app.psgi: a PSGI app is a code ref taking an env hash and returning [status, headers, body]
my $app = sub {
my $env = shift;
my $path = $env->{PATH_INFO};
return [200, ['Content-Type' => 'text/plain'], ["Hello from $path\n"]];
};plackup app.psgi # development server (port 5000)
plackup -s Starman --workers 8 app.psgi # production preforking server42.2 Mojolicious (Real-Time Web Framework, No Dependencies)
Mojolicious includes a user agent, DOM parser, JSON, WebSockets, an event loop, promises/async-await, a template engine (.ep), Test::Mojo, plugins (Mojo::Pg, Minion job queue, OpenAPI).
#!/usr/bin/env perl
use Mojolicious::Lite -signatures;
my %todos;
my $next_id = 1;
get '/' => sub ($c) { $c->render(text => 'Todo API') };
get '/todos' => sub ($c) { $c->render(json => [ values %todos ]) };
post '/todos' => sub ($c) {
my $data = $c->req->json // {};
return $c->render(json => { error => 'title required' }, status => 400) unless $data->{title};
my $todo = { id => $next_id++, title => $data->{title}, done => \0 };
$todos{ $todo->{id} } = $todo;
$c->render(json => $todo, status => 201);
};
get '/todos/:id' => [id => qr/\d+/] => sub ($c) {
my $todo = $todos{ $c->param('id') } or return $c->reply->not_found;
$c->render(json => $todo);
};
get '/hello/:name' => sub ($c) { $c->stash(name => $c->param('name')); $c->render('hello') };
websocket '/echo' => sub ($c) {
$c->on(message => sub ($c, $msg) { $c->send("echo: $msg") });
};
app->start;
__DATA__
@@ hello.html.ep
<!DOCTYPE html>
<html><body><h1>Hello, <%= $name %>!</h1></body></html>morbo app.pl # development server with auto-reload
hypnotoad app.pl # production preforking server with zero-downtime restarts
mojo generate app MyApp # full app structure (controllers, templates, tests)42.3 Dancer2 (Lightweight, Sinatra-Like)
package MyApp;
use Dancer2;
set serializer => 'JSON';
get '/' => sub { { message => 'Hello Dancer2' } };
get '/users/:id' => sub { my $id = route_parameters->get('id'); { id => $id } };
post '/users' => sub { my $data = body_parameters->as_hashref; status 201; $data };
true;
# Run: plackup bin/app.psgi42.4 Other Frameworks and Tools
Mature, enterprise MVC framework Kelp, Raisin (REST APIs), Web::Simple CGI.pm / CGI::Tiny Legacy CGI (removed from core in 5.22)
Template Toolkit, Text::Xslate, Mojo::Template Job queue (PostgreSQL/SQLite/Redis backends)
Crypt::JWT, Mojolicious::Plugin::OAuth2, Authen::Passphrase