NAME
Mojolicious::Guides::Cookbook - Cookbook
OVERVIEW
Cooking with Mojolicious, recipes for every taste.
DEPLOYMENT
Getting Mojolicious and Mojolicious::Lite applications running on different platforms.
Builtin Server
Mojolicious contains a very portable HTTP 1.1 compliant web server. It is usally 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://*:3000.
A development certificate for testing purposes is built right in, so it just works.
Hypnotoad
For bigger applications Mojolicious contains the UNIX optimized preforking web server 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 builtin web server but optimized specifically for production environments out of the box.
% hypnotoad script/myapp
Server available at http://*: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 Mojolicious, Perl or even system libraries at runtime without ever stopping the server or losing a single incoming connection, just by sending it a USR2
signal.
% kill -s 'USR2' `cat hypnotoad.pid`
Nginx
One of the most popular setups these days is the builtin 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 hypnotoad
if your proxy is on a different physical machine than your application and can't be auto detected.
# hypnotoad.conf
{proxy => 1};
Apache/CGI
CGI
is supported out of the box and your Mojolicious application will automatically detect that it is executed as a CGI
script.
<VirtualHost *:80>
ServerName localhost
DocumentRoot /home/sri/myapp/public
ScriptAlias /myapp "/home/sri/myapp/script/myapp"
</VirtualHost>
Apache/FastCGI
FastCGI
is also supported out of the box and your Mojolicious application will automatically detect that it is executed as a FastCGI
script.
<VirtualHost *:80>
ServerName localhost
DocumentRoot /home/sri/myapp/public
FastCgiServer /home/sri/myapp/script/myapp -processes 10
Alias /myapp /home/sri/myapp/script/myapp
</VirtualHost>
PSGI/Plack
PSGI is an interface between Perl web frameworks and web servers, and Plack is a Perl module and toolkit that contains PSGI middleware, helpers and adapters to web servers. PSGI and Plack are inspired by Python's WSGI and Ruby's Rack. Mojolicious applications are ridiculously simple to deploy with Plack.
% plackup ./script/myapp
HTTP::Server::PSGI: Accepting connections at http://0:5000/
Plack provides many server and protocol adapters for you to choose from such as FCGI
, SCGI
and mod_perl
. Make sure to run plackup
from your applications home directory, otherwise libraries might not be found.
% plackup ./script/myapp -s FCGI -l /tmp/myapp.sock
Because plackup
uses a weird trick to load your script, Mojolicious is not always able to detect the applications home directory, if thats the case you can simply use the MOJO_HOME
environment variable. Also note that app->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 .psgi
file, if thats 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 PLACK_ENV
environment variable.
Apache/mod_perl (PSGI/Plack)
mod_perl
is a good example for a PSGI adapter that is used without plackup
, note that setting the PLACK_ENV
environment variable is required for Mojolicious PSGI detection.
<VirtualHost *:80>
ServerName localhost
DocumentRoot /home/sri/myapp/public
<Perl>
$ENV{PLACK_ENV} = 'production';
$ENV{MOJO_HOME} = '/home/sri/myapp';
</Perl>
<Location /myapp>
SetHandler perl-script
PerlHandler Plack::Handler::Apache2
PerlSetVar psgi_app /home/sri/myapp/script/myapp
</Location>
</VirtualHost>
IIS6.0/FastCGI
We don't suggest using IIS, it is a horribly broken web server, avoid it if you can. There is nothing we can do to make this a pleasant experience for you, but maybe we can at least ease some of the pain.
First you should make sure to get recent versions of Strawberry Perl
and Mojolicious installed, Strawberry
is as good as a Windows version of Perl can be.
Then you'll have to install IIS 6.0 and its FastCGI extension, which is not part of the standard installation. Create a new website with Control Panel
> Administrative Tools
> Internet Information Services Manager
> Action
> New
> Web Site
and finish the installation wizard.
Open your newly created websites properties and select the tab Web Site
. Set the proper values for Site Description
, IP Address
, TCP Port
, SSL Port
etc.
On the tab Home Directory
set Local Path
to c:\myapp\public
, Local Path Permission Flags
to Read
and Log Visits
, Execute Permissions
to Scripts Only
.
Click on the Configuration
button and then Insert
(next to Wildcard Application Mappings
). In the next dialog set Executable
to c:\windows\system32\inetsrv\fcgiext.dll
and uncheck Verify That Files Exist
.
Now put the following lines into c:\windows\system32\inetsrv\fcgiext.ini
or c:\windows\syswow64\inetsrv\fcgiext.ini
on 64-bit systems.
[Types]
*=MyApp
[MyApp]
ExePath=c:\strawberry\perl\bin\perl.exe
Arguments="c:\myapp\script\myapp fastcgi"
; Let IIS serve static files
IgnoreExistingFiles=0
IgnoreDirectories=1
There is one more thing, IIS sometimes clears your environment variables but Windows won't work without SYSTEMROOT
, so you might have to set it manually in your application.
# Application
package MyApp;
use base 'Mojolicious';
sub startup {
my $self = shift;
# Use event hook to set environment variable for every request
$self->hook(
before_dispatch => sub { $ENV{SYSTEMROOT} = 'c:\\winnt' }
);
}
1;
CLIENT
When we say Mojolicious is a web framework we actually mean it.
Streaming
Receiving a streaming response can be really tricky in most HTTP clients, Mojo::Client makes it actually easy.
my $client = Mojo::Client->new;
my $tx = $client->build_tx(GET => 'http://mojolicio.us');
$tx->res->body(sub { print $_[1] });
$client->start($tx);
The body
callback will be called for every chunk of data that is received, even chunked
encoding will be handled transparently if neccessary.
JAVASCRIPT
jQuery (Content Distribution Network)
These days 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
'http://ajax.googleapis.com/ajax/libs/jquery/1.4/jquery.min.js' %>
<%= 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 %>
HACKS
Fun hacks you might not use very often but that might come in handy some day.
Rewriting
Sometimes you might have to deploy your application in a broken blackbox environment where you can't just fix the server configuration. In such cases you can use a 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';
});
Hello World
If every byte matters this is the smallest Hello World
application you can write with Mojolicious::Lite.
use Mojolicious::Lite;
get '/' => {text => 'Hello World!'};
app->start;
It works because automatic rendering kicks in even if no actual code gets executed by the router, the renderer just picks up the text
value from the stash and generates a response.