NAME
Mojolicious::Lite - Real-time micro web framework
SYNOPSIS
# Automatically enables "strict", "warnings" and Perl 5.10 features
use
Mojolicious::Lite;
# Route with placeholder
get
'/:foo'
=>
sub
{
my
$self
=
shift
;
my
$foo
=
$self
->param(
'foo'
);
$self
->render(
text
=>
"Hello from $foo!"
);
};
# Start the Mojolicious command system
app->start;
DESCRIPTION
Mojolicious::Lite is a micro real-time web framework built around Mojolicious.
TUTORIAL
A quick example driven introduction to the wonders of Mojolicious::Lite. Most of what you'll learn here also applies to normal Mojolicious applications.
Hello World!
A simple Hello World application can look like this, strict, warnings and Perl 5.10 features are automatically enabled and a few functions imported when you use Mojolicious::Lite, turning your script into a full featured web application.
#!/usr/bin/env perl
use
Mojolicious::Lite;
get
'/'
=>
sub
{
my
$self
=
shift
;
$self
->render(
text
=>
'Hello World!'
);
};
app->start;
Generator
There is also a helper command to generate a small example application.
$ mojo generate lite_app
Commands
All the normal Mojolicious::Commands are available from the command line. Note that CGI and PSGI environments can usually be auto detected and will just work without commands.
$ ./myapp.pl daemon
Server available at http://127.0.0.1:3000.
Server available at http://127.0.0.1:8080.
$ ./myapp.pl cgi
...CGI output...
$ ./myapp.pl
...List of available commands (or automatically detected environment)...
Start
The app->start call that starts the Mojolicious command system can be customized to override normal @ARGV
use.
app->start(
'cgi'
);
Reloading
Your application will automatically reload itself if you start it with the morbo
development web server, so you don't have to restart the server after every change.
$ morbo myapp.pl
Server available at http://127.0.0.1:3000.
Routes
Routes are basically just fancy paths that can contain different kinds of placeholders. $self
is an instance of Mojolicious::Controller containing both the HTTP request and response.
# /foo
get
'/foo'
=>
sub
{
my
$self
=
shift
;
$self
->render(
text
=>
'Hello World!'
);
};
GET/POST parameters
All GET
and POST
parameters are accessible via param
.
# /foo?user=sri
get
'/foo'
=>
sub
{
my
$self
=
shift
;
my
$user
=
$self
->param(
'user'
);
$self
->render(
text
=>
"Hello $user!"
);
};
Stash and templates
The stash
is used to pass data to templates, which can be inlined in the DATA
section.
# /bar
get
'/bar'
=>
sub
{
my
$self
=
shift
;
$self
->stash(
one
=> 23);
$self
->render(
'baz'
,
two
=> 24);
};
__DATA__
@@ baz.html.ep
The magic numbers are <%= $one %> and <%= $two %>.
For more information about templates see also "Embedded Perl" in Mojolicious::Guides::Rendering.
HTTP
Mojo::Message::Request and Mojo::Message::Response give you full access to all HTTP features and information.
# /agent
get
'/agent'
=>
sub
{
my
$self
=
shift
;
$self
->res->headers->header(
'X-Bender'
=>
'Bite my shiny metal ass!'
);
$self
->render(
text
=>
$self
->req->headers->user_agent);
};
Route names
All routes can have a name associated with them, this allows automatic template detection and back referencing with url_for
, link_to
and form_for
. Nameless routes get an automatically generated one assigned that is simply equal to the route itself without non-word characters.
# /
get
'/'
=>
'index'
;
# /hello
get
'/hello'
;
__DATA__
@@ index.html.ep
<%= link_to Hello => 'hello' %>.
<%= link_to Reload => 'index' %>.
@@ hello.html.ep
Hello World!
Layouts
Templates can have layouts.
# /with_layout
get
'/with_layout'
=>
sub
{
my
$self
=
shift
;
$self
->render(
'with_layout'
);
};
__DATA__
@@ with_layout.html.ep
% title 'Green!';
% layout 'green';
Hello World!
@@ layouts/green.html.ep
<!doctype html><html>
<head><title><%= title %></title></head>
<body><%= content %></body>
</html>
Blocks
Template blocks can be used like normal Perl functions and are always delimited by the begin
and end
keywords.
# /with_block
get
'/with_block'
=>
'block'
;
__DATA__
@@ block.html.ep
% my $link = begin
% my ($url, $name) = @_;
Try <%= link_to $url => begin %><%= $name %><% end %>!
% end
<!doctype html><html>
<head><title>Sebastians frameworks!</title></head>
<body>
%= $link->('http://mojolicio.us', 'Mojolicious')
%= $link->('http://catalystframework.org', 'Catalyst')
</body>
</html>
Captured content
The content_for
helper can be used to pass around blocks of captured content.
# /captured
get
'/captured'
=>
sub
{
my
$self
=
shift
;
$self
->render(
'captured'
);
};
__DATA__
@@ captured.html.ep
% layout 'blue', title => 'Green!';
% content_for header => begin
<meta http-equiv="Pragma" content="no-cache">
% end
Hello World!
% content_for header => begin
<meta http-equiv="Expires" content="-1">
% end
@@ layouts/blue.html.ep
<!doctype html><html>
<head>
<title><%= title %></title>
%= content_for 'header'
</head>
<body><%= content %></body>
</html>
Helpers
You can also extend Mojolicious with your own helpers, a list of all built-in ones can be found in Mojolicious::Plugin::DefaultHelpers and Mojolicious::Plugin::TagHelpers.
# "whois" helper
helper
whois
=>
sub
{
my
$self
=
shift
;
my
$agent
=
$self
->req->headers->user_agent ||
'Anonymous'
;
my
$ip
=
$self
->tx->remote_address;
return
"$agent ($ip)"
;
};
# /secret
get
'/secret'
=>
sub
{
my
$self
=
shift
;
my
$user
=
$self
->whois;
$self
->app->
log
->debug(
"Request from $user."
);
};
__DATA__
@@ secret.html.ep
We know who you are <%= whois %>.
Placeholders
Route placeholders allow capturing parts of a request path until a /
or .
separator occurs, results will be stored by name in the stash
and param
.
# /foo/test
# /foo/test123
get
'/foo/:bar'
=>
sub
{
my
$self
=
shift
;
my
$bar
=
$self
->stash(
'bar'
);
$self
->render(
text
=>
"Our :bar placeholder matched $bar"
);
};
# /testsomething/foo
# /test123something/foo
get
'/(:bar)something/foo'
=>
sub
{
my
$self
=
shift
;
my
$bar
=
$self
->param(
'bar'
);
$self
->render(
text
=>
"Our :bar placeholder matched $bar"
);
};
Wildcard placeholders
Wildcard placeholders allow matching absolutely everything, including /
and .
.
# /hello/test
# /hello/test123
# /hello/test.123/test/123
get
'/hello/*you'
=>
'groovy'
;
__DATA__
@@ groovy.html.ep
Your name is <%= $you %>.
HTTP methods
Routes can be restricted to specific request methods.
# GET /bye
get
'/bye'
=>
sub
{
my
$self
=
shift
;
$self
->render(
text
=>
'Bye!'
);
};
# POST /bye
post
'/bye'
=>
sub
{
my
$self
=
shift
;
$self
->render(
text
=>
'Bye!'
);
};
# GET|POST|DELETE /bye
any [
'get'
,
'post'
,
'delete'
] =>
'/bye'
=>
sub
{
my
$self
=
shift
;
$self
->render(
text
=>
'Bye!'
);
};
# * /baz
any
'/baz'
=>
sub
{
my
$self
=
shift
;
my
$method
=
$self
->req->method;
$self
->render(
text
=>
"You called /baz with $method"
);
};
Optional placeholders
Routes allow default values to make placeholders optional.
# /hello
# /hello/Sara
get
'/hello/:name'
=> {
name
=>
'Sebastian'
} =>
sub
{
my
$self
=
shift
;
$self
->render(
'groovy'
,
format
=>
'txt'
);
};
__DATA__
@@ groovy.txt.ep
My name is <%= $name %>.
Restrictive placeholders
The easiest way to make placeholders more restrictive are alternatives, you just make a list of possible values.
# /test
# /123
any
'/:foo'
=> [
foo
=> [
'test'
, 123]] =>
sub
{
my
$self
=
shift
;
my
$foo
=
$self
->param(
'foo'
);
$self
->render(
text
=>
"Our :foo placeholder matched $foo"
);
};
All placeholders get compiled to a regex internally, this process can also be easily customized.
# /1
# /123
any
'/:bar'
=> [
bar
=>
qr/\d+/
] =>
sub
{
my
$self
=
shift
;
my
$bar
=
$self
->param(
'bar'
);
$self
->render(
text
=>
"Our :bar placeholder matched $bar"
);
};
Just make sure not to use ^
and $
or capturing groups (...)
, because placeholders become part of a larger regular expression internally, (?:...)
is fine though.
Formats
Formats can be automatically detected by looking at file extensions.
# /detection.html
# /detection.txt
get
'/detection'
=>
sub
{
my
$self
=
shift
;
$self
->render(
'detected'
);
};
__DATA__
@@ detected.html.ep
<!doctype html><html>
<head><title>Detected!</title></head>
<body>HTML was detected.</body>
</html>
@@ detected.txt.ep
TXT was detected.
Restrictive placeholders can also be used for format detection.
# /hello.json
# /hello.txt
get
'/hello'
=> [
format
=> [
'json'
,
'txt'
]] =>
sub
{
my
$self
=
shift
;
return
$self
->render_json({
hello
=>
'world!'
})
if
$self
->stash(
'format'
) eq
'json'
;
$self
->render_text(
'hello world!'
);
};
Content negotiation
For resources with different representations and that require truly RESTful
content negotiation you can also use respond_to
.
# /hello (Accept: application/json)
# /hello (Accept: text/xml)
# /hello.json
# /hello.xml
# /hello?format=json
# /hello?format=xml
get
'/hello'
=>
sub
{
my
$self
=
shift
;
$self
->respond_to(
json
=> {
json
=> {
hello
=>
'world'
}},
xml
=> {
text
=>
'<hello>world</hello>'
},
any
=> {
data
=>
''
,
status
=> 204}
);
};
MIME type mappings can be extended or changed easily with "types" in Mojolicious.
app->types->type(
rdf
=>
'application/rdf+xml'
);
Under
Authentication and code shared between multiple routes can be realized easily with the under
statement. All following routes are only evaluated if the under
callback returned a true value.
use
Mojolicious::Lite;
# Authenticate based on name parameter
under
sub
{
my
$self
=
shift
;
# Authenticated
my
$name
=
$self
->param(
'name'
) ||
''
;
return
1
if
$name
eq
'Bender'
;
# Not authenticated
$self
->render(
'denied'
);
return
;
};
# / (with authentication)
get
'/'
=>
'index'
;
app->start;
__DATA__;
@@ denied.html.ep
You are not Bender, permission denied!
@@ index.html.ep
Hi Bender!
Prefixing multiple routes is another good use for under
.
use
Mojolicious::Lite;
# /foo
under
'/foo'
;
# /foo/bar
get
'/bar'
=> {
text
=>
'foo bar!'
};
# /foo/baz
get
'/baz'
=> {
text
=>
'foo baz!'
};
# /
under
'/'
=> {
message
=>
'whatever'
};
# /bar
get
'/bar'
=> {
inline
=>
'<%= $message %> works!'
};
app->start;
You can also group
related routes, which allows nesting of multiple under
statements.
use
Mojolicious::Lite;
# Global logic shared by all routes
under
sub
{
my
$self
=
shift
;
return
1
if
$self
->req->headers->header(
'X-Bender'
);
$self
->render(
text
=>
"You're not Bender!"
);
return
;
};
# Admin section
group {
# Local logic shared only by routes in this group
under
'/admin'
=>
sub
{
my
$self
=
shift
;
return
1
if
$self
->req->heaers->header(
'X-Awesome'
);
$self
->render(
text
=>
"You're not awesome enough!"
);
return
;
};
# GET /admin/dashboard
get
'/dashboard'
=> {
text
=>
'Nothing to see here yet!'
};
};
# GET /welcome
get
'/welcome'
=> {
text
=>
'Hi Bender!'
};
app->start;
Conditions
Conditions such as agent
and host
from Mojolicious::Plugin::HeaderCondition allow even more powerful route constructs.
# /foo (Firefox)
get
'/foo'
=> (
agent
=>
qr/Firefox/
) =>
sub
{
my
$self
=
shift
;
$self
->render(
text
=>
'Congratulations, you are using a cool browser!'
);
};
# /foo (Internet Explorer)
get
'/foo'
=> (
agent
=>
qr/Internet Explorer/
) =>
sub
{
my
$self
=
shift
;
$self
->render(
text
=>
'Dude, you really need to upgrade to Firefox!'
);
};
get
'/bar'
=> (
host
=>
'mojolicio.us'
) =>
sub
{
my
$self
=
shift
;
$self
->render(
text
=>
'Hello Mojolicious!'
);
};
Sessions
Signed cookie based sessions just work out of the box as soon as you start using them.
use
Mojolicious::Lite;
get
'/counter'
=>
sub
{
my
$self
=
shift
;
$self
->session->{counter}++;
};
app->start;
__DATA__
@@ counter.html.ep
Counter: <%= session 'counter' %>
Secret
Note that you should use a custom secret
to make signed cookies really secure.
app->secret(
'My secret passphrase here!'
);
File uploads
All files uploaded via multipart/form-data
request are automatically available as Mojo::Upload instances. And you don't have to worry about memory usage, because all files above 250KB
will be automatically streamed into a temporary file.
use
Mojolicious::Lite;
any
'/upload'
=>
sub
{
my
$self
=
shift
;
if
(
my
$example
=
$self
->req->upload(
'example'
)) {
my
$size
=
$example
->size;
my
$name
=
$example
->filename;
$self
->render(
text
=>
"Thanks for uploading $size byte file $name."
);
}
};
app->start;
__DATA__
@@ upload.html.ep
<!doctype html><html>
<head><title>Upload</title></head>
<body>
% my @attrs = (method => 'POST', enctype => 'multipart/form-data');
%= form_for upload => @attrs => begin
%= file_field 'example'
%= submit_button 'Upload'
% end
</body>
</html>
To protect you from excessively large files there is also a global limit of 5MB
by default, which you can tweak with the MOJO_MAX_MESSAGE_SIZE
environment variable.
# Increase limit to 1GB
$ENV
{MOJO_MAX_MESSAGE_SIZE} = 1073741824;
User agent
With Mojo::UserAgent there's a full featured HTTP 1.1 and WebSocket user agent built right in. Especially in combination with Mojo::JSON and Mojo::DOM this can be a very powerful tool.
get
'/test'
=>
sub
{
my
$self
=
shift
;
};
WebSockets
WebSocket applications have never been this easy before.
websocket
'/echo'
=>
sub
{
my
$self
=
shift
;
$self
->on_message(
sub
{
my
(
$self
,
$message
) =
@_
;
$self
->send_message(
"echo: $message"
);
});
};
External templates
External templates will be searched by the renderer in a templates
directory.
# /external
any
'/external'
=>
sub
{
my
$self
=
shift
;
# templates/foo/bar.html.ep
$self
->render(
'foo/bar'
);
};
Static files
Static files will be automatically served from the DATA
section (even Base64 encoded) or a public
directory if it exists.
@@ something.js
alert(
'hello!'
);
@@ test.txt (base64)
dGVzdCAxMjMKbGFsYWxh
$
mkdir
public
$ mv something.js public/something.js
Testing
Testing your application is as easy as creating a t
directory and filling it with normal Perl unit tests.
use
Test::Mojo;
use
FindBin;
require
"$FindBin::Bin/../myapp.pl"
;
my
$t
= Test::Mojo->new;
$t
->get_ok(
'/'
)->status_is(200)->content_like(
qr/Funky!/
);
Run all unit tests with the test
command.
$ ./myapp.pl test
To make your tests more noisy and show you all log messages you can also change the application log level directly in your test files.
$t
->app->
log
->level(
'debug'
);
Mode
To disable debug messages later in a production setup you can change the Mojolicious mode, default will be development
.
$ ./myapp.pl --mode production
Logging
Mojo::Log messages will be automatically written to STDERR
or a log/$mode.log
file if a log
directory exists.
$
mkdir
log
For more control the Mojolicious instance can be accessed directly.
app->
log
->level(
'error'
);
app->routes->route(
'/foo/:bar'
)->via(
'GET'
)->to(
cb
=>
sub
{
my
$self
=
shift
;
$self
->app->
log
->debug(
'Got a request for "Hello Mojo!".'
);
$self
->render(
text
=>
'Hello Mojo!'
);
});
Growing
In case a lite app needs to grow, lite and real Mojolicious applications can be easily mixed to make the transition process very smooth.
package
MyApp::Foo;
sub
index
{
my
$self
=
shift
;
$self
->render(
text
=>
'It works!'
);
}
package
main;
use
Mojolicious::Lite;
get
'/bar'
=>
sub
{
my
$self
=
shift
;
$self
->render(
text
=>
'This too!'
);
};
app->routes->namespace(
'MyApp'
);
app->routes->route(
'/foo/:action'
)->via(
'GET'
)->to(
'foo#index'
);
app->start;
There is also a helper command to generate a full Mojolicious example that will let you explore the astonishing similarities between Mojolicious::Lite and Mojolicious applications. Both share about 99% of the same code, so almost everything you learned in this tutorial applies there too. :)
$ mojo generate app
More
You can continue with Mojolicious::Guides now, and don't forget to have fun!
FUNCTIONS
Mojolicious::Lite implements the following functions.
any
my
$route
= any
'/:foo'
=>
sub
{...};
my
$route
= any [
'get'
,
'post'
] =>
'/:foo'
=>
sub
{...};
Generate route matching any of the listed HTTP request methods or all. See also the tutorial above for more argument variations.
app
my
$app
= app;
The Mojolicious::Lite application.
del
my
$route
= del
'/:foo'
=>
sub
{...};
Generate route matching only DELETE
requests. See also the tutorial above for more argument variations.
get
my
$route
= get
'/:foo'
=>
sub
{...};
Generate route matching only GET
requests. See also the tutorial above for more argument variations.
group
group {...};
Start a new route group. Note that this function is EXPERIMENTAL and might change without warning!
helper
helper
foo
=>
sub
{...};
Alias for "helper" in Mojolicious. Note that this function is EXPERIMENTAL and might change without warning!
hook
hook
after_dispatch
=>
sub
{...};
Alias for "hook" in Mojolicious. Note that this function is EXPERIMENTAL and might change without warning!
plugin
plugin
'SomeThing'
;
Alias for "plugin" in Mojolicious.
post
my
$route
= post
'/:foo'
=>
sub
{...};
Generate route matching only POST
requests. See also the tutorial above for more argument variations.
put
my
$route
= put
'/:foo'
=>
sub
{...};
Generate route matching only PUT
requests. See also the tutorial above for more argument variations.
under
my
$route
= under
sub
{...};
my
$route
= under
'/:foo'
;
Generate bridge to which all following routes are automatically appended. See also the tutorial above for more argument variations.
websocket
my
$route
= websocket
'/:foo'
=>
sub
{...};
Generate route matching only WebSocket
handshakes. See also the tutorial above for more argument variations.
ATTRIBUTES
Mojolicious::Lite inherits all attributes from Mojolicious.
METHODS
Mojolicious::Lite inherits all methods from Mojolicious.