—=head1 NAME
Mojolicious::Guides::Cookbook - Cookbook
=head1 OVERVIEW
Cooking with L<Mojolicious>, recipes for every taste.
=head1 DEPLOYMENT
Getting L<Mojolicious> and L<Mojolicious::Lite> applications running on
different platforms.
=head2 Built-in Server
L<Mojolicious> contains a very portable HTTP 1.1 compliant web server.
It is usually used during development but is solid and fast enough for small
to mid sized applications.
$ ./script/myapp daemon
Server available at http://127.0.0.1:3000.
It has many configuration options and is known to work on every platform
Perl works on.
$ ./script/myapp help daemon
...List of available options...
Another huge advantage is that it supports TLS and WebSockets out of the box.
$ ./script/myapp daemon --listen https://*:3000
Server available at https://127.0.0.1:3000.
A development certificate for testing purposes is built right in, so it just
works.
=head2 Hypnotoad
For bigger applications L<Mojolicious> contains the UNIX optimized preforking
web server L<Mojo::Server::Hypnotoad> that will allow you to take advantage
of multiple cpu cores and copy-on-write.
Mojo::Server::Hypnotoad
|- Mojo::Server::Daemon [1]
|- Mojo::Server::Daemon [2]
|- Mojo::Server::Daemon [3]
`- Mojo::Server::Daemon [4]
It is based on the normal built-in web server but optimized specifically for
production environments out of the box.
$ hypnotoad script/myapp
Server available at http://127.0.0.1:8080.
Config files are plain Perl scripts for maximal customizability.
# hypnotoad.conf
{listen => ['http://*:80'], workers => 10};
But one of its biggest advantages is the support for effortless zero downtime
software upgrades.
That means you can upgrade L<Mojolicious>, Perl or even system libraries at
runtime without ever stopping the server or losing a single incoming
connection, just by running the command above again.
$ hypnotoad script/myapp
Starting hot deployment for Hypnotoad server 31841.
=head2 Nginx
One of the most popular setups these days is the built-in web server behind a
Nginx reverse proxy.
upstream myapp {
server 127.0.0.1:8080;
}
server {
listen 80;
server_name localhost;
location / {
proxy_read_timeout 300;
proxy_pass http://myapp;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
You might also want to enable reverse proxy support in C<hypnotoad>.
This allows L<Mojolicious> to automatically pick up the C<X-Forwarded-For>,
C<X-Forwarded-Host> and C<X-Forwarded-HTTPS> headers.
# hypnotoad.conf
{proxy => 1};
=head2 Apache/CGI
C<CGI> is supported out of the box and your L<Mojolicious> application will
automatically detect that it is executed as a C<CGI> script.
ScriptAlias / /home/sri/myapp/script/myapp/
=head2 Apache/FastCGI
C<FastCGI> is also supported out of the box and your L<Mojolicious>
application will automatically detect that it is executed as a C<FastCGI>
script.
FastCgiIpcDir /home/sri/myapp
FastCgiServer /home/sri/myapp/script/myapp -processes 1
Alias / /home/sri/myapp/script/myapp/
=head2 PSGI/Plack
L<PSGI> is an interface between Perl web frameworks and web servers, and
L<Plack> is a Perl module and toolkit that contains PSGI middleware, helpers
and adapters to web servers.
L<PSGI> and L<Plack> are inspired by Python's WSGI and Ruby's Rack.
L<Mojolicious> applications are ridiculously simple to deploy with L<Plack>.
$ plackup ./script/myapp
HTTP::Server::PSGI: Accepting connections at http://0:5000/
L<Plack> provides many server and protocol adapters for you to choose from
such as C<FCGI>, C<SCGI> and C<mod_perl>.
Make sure to run C<plackup> from your applications home directory, otherwise
libraries might not be found.
$ plackup ./script/myapp -s FCGI -l /tmp/myapp.sock
Because C<plackup> uses a weird trick to load your script, L<Mojolicious> is
not always able to detect the applications home directory, if that's the case
you can simply use the C<MOJO_HOME> environment variable.
Also note that C<app-E<gt>start> needs to be the last Perl statement in the
application script for the same reason.
$ MOJO_HOME=/home/sri/myapp plackup ./script/myapp
HTTP::Server::PSGI: Accepting connections at http://0:5000/
Some server adapters might ask for a C<.psgi> file, if that's the case you
can just point them at your application script because it will automatically
act like one if it detects the presence of a C<PLACK_ENV> environment
variable.
=head2 Plack Middleware
You can even use middleware right in your application.
use Mojolicious::Lite;
use Plack::Builder;
get '/welcome' => sub {
my $self = shift;
$self->render(text => 'Hello Mojo!');
};
builder {
enable 'Deflater';
app->start;
};
=head2 Apache/mod_perl (PSGI/Plack)
C<mod_perl> is a good example for a L<PSGI> adapter that is used without
C<plackup>, note that setting the C<PLACK_ENV> environment variable is
required for L<Mojolicious> L<PSGI> detection.
<VirtualHost *:80>
ServerName localhost
DocumentRoot /home/sri/myapp/public
<Perl>
$ENV{PLACK_ENV} = 'production';
$ENV{MOJO_HOME} = '/home/sri/myapp';
$ENV{MOJO_MODE} = 'deployment';
</Perl>
<Location /myapp>
SetHandler perl-script
PerlHandler Plack::Handler::Apache2
PerlSetVar psgi_app /home/sri/myapp/script/myapp
</Location>
</VirtualHost>
=head2 Rewriting
Sometimes you might have to deploy your application in a blackbox environment
where you can't just change the server configuration or behind a reverse
proxy that passes along additional information with C<X-*> headers.
In such cases you can use a C<before_dispatch> hook to rewrite incoming
requests.
app->hook(before_dispatch => sub {
my $self = shift;
$self->req->url->base->scheme('https')
if $self->req->headers->header('X-Forwarded-Protocol') eq 'https';
});
=head2 Embedding
From time to time you might want to reuse parts of L<Mojolicious>
applications like configuration files, database connection or helpers for
other scripts, with this little mock server you can just embed them.
use Mojo::Server;
# Load application with mock server
my $server = Mojo::Server->new;
my $app = $server->load_app('./myapp.pl');
# Access fully initialized application
print $app->static->root;
You can also use the built-in web server to embed L<Mojolicious> applications
into alien environments like foreign event loops.
use Mojolicious::Lite;
use Mojo::Server::Daemon;
# Normal action
get '/' => sub {
my $self = shift;
$self->render(text => 'Hello World!');
};
# Connect application with custom daemon
my $daemon =
Mojo::Server::Daemon->new(app => app, listen => ['http://*:8080']);
$daemon->prepare_ioloop;
# Call "one_tick" repeatedly from the alien environment
$daemon->ioloop->one_tick while 1;
=head1 USER AGENT
When we say L<Mojolicious> is a web framework we actually mean it.
=head2 Web Scraping
Scraping information from web sites has never been this much fun before.
The built-in HTML5/XML parser L<Mojo::DOM> supports all CSS3 selectors that
make sense for a standalone parser.
# Fetch web site
my $ua = Mojo::UserAgent->new;
my $tx = $ua->get('mojolicio.us/perldoc');
# Extract title
print 'Title: ', $tx->res->dom->at('head > title')->text, "\n";
# Extract headings
$tx->res->dom('h1, h2, h3')->each(sub {
print 'Heading: ', shift->all_text, "\n";
});
Especially for unit testing your L<Mojolicious> applications this can be a
very powerful tool.
=head2 JSON Web Services
Most web services these days are based on the JSON data-interchange format.
That's why L<Mojolicious> comes with the possibly fastest pure-Perl
implementation L<Mojo::JSON> built right in.
# Fresh user agent
my $ua = Mojo::UserAgent->new;
# Fetch the latest news about Mojolicious from Twitter
my $search = 'http://search.twitter.com/search.json?q=Mojolicious';
for $tweet (@{$ua->get($search)->res->json->{results}}) {
# Tweet text
my $text = $tweet->{text};
# Twitter user
my $user = $tweet->{from_user};
# Show both
my $result = "$text --$user\n\n";
utf8::encode $result;
print $result;
}
=head2 Basic Authentication
You can just add username and password to the URL.
my $ua = Mojo::UserAgent->new;
print $ua->get('https://sri:secret@mojolicio.us/hideout')->res->body;
=head2 Decorating Followup Requests
L<Mojo::UserAgent> can automatically follow redirects, the C<on_start>
callback allows you direct access to each transaction right after they have
been initialized and before a connection gets associated with them.
# User agent following up to 10 redirects
my $ua = Mojo::UserAgent->new(max_redirects => 10);
# Add a witty header to every request
$ua->on_start(sub {
my $tx = pop;
$tx->req->headers->header('X-Bender' => 'Bite my shiny metal ass!');
print 'Request: ', $tx->req->url->clone->to_abs, "\n";
});
# Request that will most likely get redirected
print 'Title: ',
$ua->get('google.com')->res->dom->at('head > title')->text, "\n";
This even works for proxy C<CONNECT> requests.
=head2 Streaming Response
Receiving a streaming response can be really tricky in most HTTP clients,
L<Mojo::UserAgent> makes it actually easy.
my $ua = Mojo::UserAgent->new;
my $tx = $ua->build_tx(GET => 'http://mojolicio.us');
$tx->res->body(sub { print $_[1] });
$ua->start($tx);
The C<body> callback will be called for every chunk of data that is received,
even C<chunked> encoding will be handled transparently if necessary.
=head2 Streaming Request
Sending a streaming request is almost just as easy.
my $ua = Mojo::UserAgent->new;
my $tx = $ua->build_tx(GET => 'http://mojolicio.us');
my $content = 'Hello world!';
$tx->req->headers->content_length(length $content);
my $drain;
$drain = sub {
my $req = shift;
my $chunk = substr $content, 0, 1, '';
$drain = undef unless length $content;
$req->write($chunk, $drain);
};
$drain->($tx->req);
$ua->start($tx);
The drain callback passed to C<write> will be invoked whenever the entire
previous chunk has been written to the kernel send buffer.
=head2 Large File Downloads
When downloading large files with L<Mojo::UserAgent> you don't have to worry
about memory usage at all, because it will automatically stream everything
above C<250KB> into a temporary file.
# Lets fetch the latest Mojolicious tarball
my $ua = Mojo::UserAgent->new(max_redirects => 5);
my $tx = $ua->get('latest.mojolicio.us');
$tx->res->content->asset->move_to('mojo.tar.gz');
To protect you from excessively large files there is also a global limit of
C<5MB> by default, which you can tweak with the C<MOJO_MAX_MESSAGE_SIZE>
environment variable.
# Increase limit to 1GB
$ENV{MOJO_MAX_MESSAGE_SIZE} = 1073741824;
=head2 Large File Upload
Uploading a large file is even easier.
# Upload file via POST and "multipart/form-data"
my $ua = Mojo::UserAgent->new;
$ua->post_form('mojolicio.us/upload',
{image => {file => '/home/sri/hello.png'}});
And once again you don't have to worry about memory usage, all data will be
streamed directly from the file.
# Upload file via PUT
my $ua = Mojo::UserAgent->new;
my $asset = Mojo::Asset::File->new(path => '/home/sri/hello.png');
my $tx = $ua->build_tx(PUT => 'mojolicio.us/upload');
$tx->req->content->asset($asset);
$ua->start($tx);
=head2 Non-Blocking
L<Mojo::UserAgent> has been designed from the ground up to be non-blocking,
the whole blocking API is just a simple convenience wrapper.
Especially for high latency tasks like web crawling this can be extremely
useful, because you can keep many parallel connections active at the same
time.
# FIFO queue
my @urls = qw/google.com/;
# User agent following up to 5 redirects
my $ua = Mojo::UserAgent->new(max_redirects => 5);
# Crawler
my $crawl;
$crawl = sub {
my $id = shift;
# Dequeue or wait for more URLs
return Mojo::IOLoop->timer(2 => sub { $crawl->($id) })
unless my $url = shift @urls;
# Fetch non-blocking just by adding a callback
$ua->get($url => sub {
my $tx = pop;
# Extract URLs
print "[$id] $url\n";
$tx->res->dom('a[href]')->each(sub {
my $e = shift;
# Build absolute URL
my $url = Mojo::URL->new($e->{href})->to_abs($tx->req->url);
print " -> $url\n";
# Enqueue
push @urls, $url;
});
# Next
$crawl->($id);
});
};
# Start a bunch of parallel crawlers sharing the same user agent
$crawl->($_) for 1 .. 3;
# Start event loop
Mojo::IOLoop->start;
You can take full control of the L<Mojo::IOLoop> event loop.
=head2 Parallel Blocking Requests
You can emulate blocking behavior by using a L<Mojo::IOLoop> trigger to
synchronize multiple non-blocking requests.
# Synchronize non-blocking requests and capture result
my $ua = Mojo::UserAgent->new;
my $t = Mojo::IOLoop->trigger;
$ua->get('http://mojolicio.us' => $t->begin);
$ua->get('http://mojolicio.us/perldoc' => $t->begin);
my ($tx, $tx2) = $t->start;
Just be aware that the resulting transactions will be in random order.
=head2 Command Line
Don't you hate checking huge HTML files from the command line?
Thanks to the C<mojo get> command that is about to change.
You can just pick the parts that actually matter with the CSS3 selectors from
L<Mojo::DOM>.
$ mojo get http://mojolicio.us 'head > title'
How about a list of all id attributes?
$ mojo get http://mojolicio.us '*' attr id
Or the text content of all heading tags?
$ mojo get http://mojolicio.us 'h1, h2, h3' text
Maybe just the text of the third heading?
$ mojo get http://mojolicio.us 'h1, h2, h3' 3 text
You can also extract all text from nested child elements.
$ mojo get http://mojolicio.us '#mojobar' all
The request can be customized as well.
$ mojo get --method post --content 'Hello!' http://mojolicio.us
$ mojo get --header 'X-Bender: Bite my shiny metal ass!' http://google.com
You can follow redirects and view the headers for all messages.
$ mojo get --redirect --verbose http://reddit.com 'head > title'
This can be an invaluable tool for testing your applications.
$ ./myapp.pl get /welcome 'head > title'
=head1 HACKS
Fun hacks you might not use very often but that might come in handy some day.
=head2 Faster Tests
Don't you hate waiting for C<make test> to finally finish?
In newer Perl versions you can set the C<HARNESS_OPTIONS> environment
variable to take advantage of multiple cpu cores and run tests parallel.
$ HARNESS_OPTIONS=j5 make test
...
The C<j5> allows 5 tests to run at the same time, which makes for example the
L<Mojolicious> test suite finish 3 times as fast on a dual core laptop!
=head2 Running Code Against Your Application
Ever thought about running a quick oneliner against your L<Mojolicious>
application to test something?
Thanks to the C<eval> command you can do just that, the application instance
itself can be accessed via C<app>.
$ mojo generate lite_app
$ ./myapp.pl eval 'print app->static->root, "\n"'
The C<verbose> option will automatically print the return value to C<STDOUT>.
$ ./myapp.pl eval -v 'app->static->root'
=head2 Making Your Application Installable
Ever thought about releasing your L<Mojolicious> application to CPAN?
It's actually much easier than you might think.
$ mojo generate app
$ cd my_mojolicious_app
$ mv public lib/MyMojoliciousApp/
$ mv templates lib/MyMojoliciousApp/
The trick is to move the C<public> and C<templates> directories so they can
get automatically installed with the modules.
package MyMojoliciousApp;
use Mojo::Base 'Mojolicious';
use File::Basename 'dirname';
use File::Spec;
# Every CPAN module needs a version
our $VERSION = '1.0';
sub startup {
my $self = shift;
# Switch to installable home directory
$self->home->parse(
File::Spec->catdir(dirname(__FILE__), 'MyMojoliciousApp'));
# Switch to installable "public" directory
$self->static->root($self->home->rel_dir('public'));
# Switch to installable "templates" directory
$self->renderer->root($self->home->rel_dir('templates'));
$self->plugin('PODRenderer');
my $r = $self->routes;
$r->route('/welcome')->to('example#welcome');
}
1;
That's really everything, now you can package your application like any other
CPAN module.
$ ./script/my_mojolicious_app generate makefile
$ perl Makefile.PL
$ make test
$ make manifest
$ make dist
And if you have a C<PAUSE> account (which can be requested at
L<http://pause.perl.org>) even upload it.
$ mojo cpanify -u USER -p PASS MyMojoliciousApp-0.01.tar.gz
=head2 Hello World
If every byte matters this is the smallest C<Hello World> application you can
write with L<Mojolicious::Lite>.
use Mojolicious::Lite;
any {text => 'Hello World!'};
app->start;
It works because all routes without a pattern default to C</> and automatic
rendering kicks in even if no actual code gets executed by the router.
The renderer just picks up the C<text> value from the stash and generates a
response.
=head2 Hello World Oneliner
The C<Hello World> example above can get even a little bit shorter in an
L<ojo> oneliner.
perl -Mojo -e'a({text => "Hello World!"})->start' daemon
And you can use all the commands from L<Mojolicious::Commands>.
perl -Mojo -e'a({text => "Hello World!"})->start' get -v /
=head2 Keeping Mojolicious Up-To-Date
This tasty oneliner will keep your L<Mojolicious> as fresh as possible.
$ sudo sh -c "curl -L cpanmin.us | perl - http://latest.mojolicio.us"
=head2 jQuery (Content Distribution Network)
These days L<Mojolicious> ships with a bundled version of jQuery, which you
can easily use as a fallback for applications that might be used offline from
time to time.
<%= javascript
<%= javascript begin %>
if (typeof jQuery == 'undefined') {
var e = document.createElement('script');
e.src = '/js/jquery.js';
e.type = 'text/javascript';
document.getElementsByTagName("head")[0].appendChild(e);
}
<% end %>
=head1 MORE
You can continue with L<Mojolicious::Guides> now or take a look at the
Mojolicious wiki L<http://github.com/kraih/mojo/wiki>, which contains a lot
more documentation and examples by many different authors.
=cut