Scroll to navigation

Mojolicious::Lite(3pm) User Contributed Perl Documentation Mojolicious::Lite(3pm)

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.
  $ ./myapp.pl daemon -l http://*:8080
  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 a Mojolicious::Controller object 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" in Mojolicious::Controller.
  # /foo?user=sri
  get '/foo' => sub {
    my $self = shift;
    my $user = $self->param('user');
    $self->render(text => "Hello $user.");
  };

Stash and templates

The "stash" in Mojolicious::Controller 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

"req" in Mojolicious::Controller and "res" in Mojolicious::Controller 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" in Mojolicious::Controller as well as many helpers like "link_to" in Mojolicious::Plugin::TagHelpers. Nameless routes get an automatically generated one assigned that is simply equal to the route itself without non-word characters.
  # /
  get '/' => sub {
    my $self = shift;
    $self->render;
  } => '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 too, you just select one with the helper "layout" in Mojolicious::Plugin::DefaultHelpers and place the result of the current template with the helper "content" in Mojolicious::Plugin::DefaultHelpers.
  # /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 helper "content_for" in Mojolicious::Plugin::TagHelpers 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 are accessible via "stash" in Mojolicious::Controller and "param" in Mojolicious::Controller.
  # /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");
  };

Relaxed Placeholders

Relaxed placeholders allow matching of everything until a "/" occurs.
  # /test/hello
  # /test123/hello
  # /test.123/hello
  get '/#you/hello' => 'groovy';
  __DATA__
  @@ groovy.html.ep
  Your name is <%= $you %>.

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 /hello
  get '/hello' => sub {
    my $self = shift;
    $self->render(text => 'Hello World!');
  };
  # PUT /hello
  put '/hello' => sub {
    my $self = shift;
    my $size = length $self->req->body;
    $self->render(text => "You uploaded $size bytes to /hello.");
  };
  # GET|POST|PATCH /bye
  any [qw(GET POST PATCH)] => '/bye' => sub {
    my $self = shift;
    $self->render(text => 'Bye World!');
  };
  # * /whatever
  any '/whatever' => sub {
    my $self   = shift;
    my $method = $self->req->method;
    $self->render(text => "You called /whatever 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 => [qw(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.

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;

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.
  # /hello.json
  # /hello.txt
  get '/hello' => [format => [qw(json txt)]] => sub {
    my $self = shift;
    return $self->render_json({hello => 'world'})
      if $self->stash('format') eq 'json';
    $self->render_text('hello world');
  };
Or you can just disable format detection.
  # /hello
  get '/hello' => [format => 0] => {text => 'No format detection.'};
  # Disable detection and allow the following routes selective re-enabling
  under [format => 0];
  # /foo
  get '/foo' => {text => 'No format detection again.'};
  # /bar.txt
  get '/bar' => [format => 'txt'] => {text => ' Just one format.'};

Content negotiation

For resources with different representations and that require truly "RESTful" content negotiation you can also use "respond_to" in Mojolicious::Controller.
  # /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');

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.');
  };
  # http://mojolicio.us/bar
  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 through the helper "session" in Mojolicious::Plugin::DefaultHelpers.
  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" in Mojolicious 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 objects. 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;
  # Upload form in DATA section
  get '/' => 'form';
  # Multipart upload handler
  post '/upload' => sub {
    my $self = shift;
    # Check file size
    return $self->render(text => 'File is too big.', status => 200)
      if $self->req->is_limit_exceeded;
    # Process uploaded file
    return $self->redirect_to('form')
      unless my $example = $self->param('example');
    my $size = $example->size;
    my $name = $example->filename;
    $self->render(text => "Thanks for uploading $size byte file $name.");
  };
  app->start;
  __DATA__
  @@ form.html.ep
  <!DOCTYPE html>
  <html>
    <head><title>Upload</title></head>
    <body>
      %= form_for upload => (enctype => 'multipart/form-data') => begin
        %= file_field 'example'
        %= submit_button 'Upload'
      % end
    </body>
  </html>
To protect you from excessively large files there is also a 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 "ua" in Mojolicious::Controller 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;
    $self->render(data => $self->ua->get('http://mojolicio.us')->res->body);
  };

WebSockets

WebSocket applications have never been this easy before.
  websocket '/echo' => sub {
    my $self = shift;
    $self->on(message => sub {
      my ($self, $message) = @_;
      $self->send("echo: $message");
    });
  };
The event "message" in Mojo::Transaction::WebSocket, which you can subscribe to with "on" in Mojolicious::Controller, will be emitted for every new WebSocket message that is received.

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::More tests => 3;
  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 -m 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 object can be accessed directly.
  app->log->level('error');
  app->routes->get('/foo/:bar' => sub {
    my $self = shift;
    $self->app->log->debug('Got a request for "Hello Mojo!".');
    $self->render(text => 'Hello Mojo!');
  });

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 [qw(GET POST)] => '/:foo' => sub {...};
Generate route with "any" in Mojolicious::Routes::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 with "delete" in Mojolicious::Routes::Route, matching only "DELETE" requests. See also the tutorial above for more argument variations.

"get"

  my $route = get '/:foo' => sub {...};
Generate route with "get" in Mojolicious::Routes::Route, matching only "GET" requests. See also the tutorial above for more argument variations.

"group"

  group {...};
Start a new route group.

"helper"

  helper foo => sub {...};
Alias for "helper" in Mojolicious.

"hook"

  hook after_dispatch => sub {...};
Alias for "hook" in Mojolicious.

"options"

  my $route = options '/:foo' => sub {...};
Generate route with "options" in Mojolicious::Routes::Route, matching only "OPTIONS" requests. See also the tutorial above for more argument variations.

"patch"

  my $route = patch '/:foo' => sub {...};
Generate route with "patch" in Mojolicious::Routes::Route, matching only "PATCH" requests. See also the tutorial above for more argument variations.

"plugin"

  plugin 'SomeThing';
Alias for "plugin" in Mojolicious.

"post"

  my $route = post '/:foo' => sub {...};
Generate route with "post" in Mojolicious::Routes::Route, matching only "POST" requests. See also the tutorial above for more argument variations.

"put"

  my $route = put '/:foo' => sub {...};
Generate route with "put" in Mojolicious::Routes::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 with "under" in Mojolicious::Routes::Route, 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 with "websocket" in Mojolicious::Routes::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.

SEE ALSO

Mojolicious, Mojolicious::Guides, <http://mojolicio.us>.
2012-09-05 perl v5.14.2