package Mojolicious::Lite; use Mojo::Base 'Mojolicious'; # "Bender: Bite my shiny metal ass!" use Mojo::File 'path'; use Mojo::UserAgent::Server; use Mojo::Util 'monkey_patch'; sub import { # Remember executable for later $ENV{MOJO_EXE} ||= (caller)[1]; # Reuse home directory if possible local $ENV{MOJO_HOME} = path($ENV{MOJO_EXE})->dirname->to_string unless $ENV{MOJO_HOME}; # Initialize application class my $caller = caller; no strict 'refs'; push @{"${caller}::ISA"}, 'Mojolicious'; # Generate moniker based on filename my $moniker = path($ENV{MOJO_EXE})->basename('.pl', '.pm', '.t'); my $app = shift->new(moniker => $moniker); # Initialize routes without namespaces my $routes = $app->routes->namespaces([]); $app->static->classes->[0] = $app->renderer->classes->[0] = $caller; # The Mojolicious::Lite DSL my $root = $routes; for my $name (qw(any get options patch post put websocket)) { monkey_patch $caller, $name, sub { $routes->$name(@_) }; } monkey_patch($caller, $_, sub {$app}) for qw(new app); monkey_patch $caller, del => sub { $routes->delete(@_) }; monkey_patch $caller, group => sub (&) { (my $old, $root) = ($root, $routes); shift->(); ($routes, $root) = ($root, $old); }; monkey_patch $caller, helper => sub { $app->helper(@_) }, hook => sub { $app->hook(@_) }, plugin => sub { $app->plugin(@_) }, under => sub { $routes = $root->under(@_) }; # Make sure there's a default application for testing Mojo::UserAgent::Server->app($app) unless Mojo::UserAgent::Server->app; # Lite apps are strict! unshift @_, 'Mojo::Base', -strict; goto &Mojo::Base::import; } 1; =encoding utf8 =head1 NAME Mojolicious::Lite - Micro real-time web framework =head1 SYNOPSIS # Automatically enables "strict", "warnings", "utf8" and Perl 5.10 features use Mojolicious::Lite; # Route with placeholder get '/:foo' => sub { my $c = shift; my $foo = $c->param('foo'); $c->render(text => "Hello from $foo."); }; # Start the Mojolicious command system app->start; =head1 DESCRIPTION L is a tiny domain specific language built around L, made up of only about a dozen Perl functions. On Perl 5.20+ you can also use a C<-signatures> flag to enable support for L. use Mojolicious::Lite -signatures; get '/:foo' => sub ($c) { my $foo = $c->param('foo'); $c->render(text => "Hello from $foo."); }; app->start; See L for more! =head1 GROWING While L will give you a detailed introduction to growing a L prototype into a well-structured L application, here we have collected a few snippets that illustrate very well just how similar both of them are. =head2 Routes The functions L, L and friends all have equivalent methods. # Mojolicious::Lite get '/foo' => sub { my $c = shift; $c->render(text => 'Hello World!'); }; # Mojolicious sub startup { my $self = shift; my $routes = $self->routes; $routes->get('/foo' => sub { my $c = shift; $c->render(text => 'Hello World!'); }); } =head2 Application The application object you can access with the function L is the first argument passed to the C method. # Mojolicious::Lite app->max_request_size(16777216); # Mojolicious sub startup { my $self = shift; $self->max_request_size(16777216); } =head2 Plugins Instead of the L function you just use the method L. # Mojolicious::Lite plugin 'Config'; # Mojolicious sub startup { my $self = shift; $self->plugin('Config'); } =head2 Helpers Similar to plugins, instead of the L function you just use the method L. # Mojolicious::Lite helper two => sub { my $c = shift; return 1 + 1; }; # Mojolicious sub startup { my $self = shift; $self->helper(two => sub { my $c = shift; return 1 + 1; }); } =head2 Under Instead of sequential function calls, we can use methods to build a tree with nested routes, that much better illustrates how routes work internally. # Mojolicious::Lite under '/foo'; get '/bar' => sub {...}; # Mojolicious sub startup { my $self = shift; my $routes = $self->routes; my $foo = $routes->under('/foo'); $foo->get('/bar' => sub {...}); } =head1 FUNCTIONS L implements the following functions, which are automatically exported. =head2 any my $route = any '/:foo' => sub {...}; my $route = any '/:foo' => sub {...} => 'name'; my $route = any '/:foo' => {foo => 'bar'} => sub {...}; my $route = any '/:foo' => [foo => qr/\w+/] => sub {...}; my $route = any ['GET', 'POST'] => '/:foo' => sub {...}; my $route = any ['GET', 'POST'] => '/:foo' => [foo => qr/\w+/] => sub {...}; my $route = any ['GET', 'POST'] => '/:foo' => (agent => qr/Firefox/) => sub {...}; Generate route with L, matching any of the listed HTTP request methods or all. See L and L for more information. =head2 app my $app = app; Returns the L application object, which is a subclass of L. # Use all the available attributes and methods app->log->level('error'); app->defaults(foo => 'bar'); =head2 del my $route = del '/:foo' => sub {...}; my $route = del '/:foo' => sub {...} => 'name'; my $route = del '/:foo' => {foo => 'bar'} => sub {...}; my $route = del '/:foo' => [foo => qr/\w+/] => sub {...}; my $route = del '/:foo' => (agent => qr/Firefox/) => sub {...}; Generate route with L, matching only C requests. See L and L for more information. =head2 get my $route = get '/:foo' => sub {...}; my $route = get '/:foo' => sub {...} => 'name'; my $route = get '/:foo' => {foo => 'bar'} => sub {...}; my $route = get '/:foo' => [foo => qr/\w+/] => sub {...}; my $route = get '/:foo' => (agent => qr/Firefox/) => sub {...}; Generate route with L, matching only C requests. See L and L for more information. =head2 group group {...}; Start a new route group. =head2 helper helper foo => sub {...}; Add a new helper with L. =head2 hook hook after_dispatch => sub {...}; Share code with L. =head2 options my $route = options '/:foo' => sub {...}; my $route = options '/:foo' => sub {...} => 'name'; my $route = options '/:foo' => {foo => 'bar'} => sub {...}; my $route = options '/:foo' => [foo => qr/\w+/] => sub {...}; my $route = options '/:foo' => (agent => qr/Firefox/) => sub {...}; Generate route with L, matching only C requests. See L and L for more information. =head2 patch my $route = patch '/:foo' => sub {...}; my $route = patch '/:foo' => sub {...} => 'name'; my $route = patch '/:foo' => {foo => 'bar'} => sub {...}; my $route = patch '/:foo' => [foo => qr/\w+/] => sub {...}; my $route = patch '/:foo' => (agent => qr/Firefox/) => sub {...}; Generate route with L, matching only C requests. See L and L for more information. =head2 plugin plugin SomePlugin => {foo => 23}; Load a plugin with L. =head2 post my $route = post '/:foo' => sub {...}; my $route = post '/:foo' => sub {...} => 'name'; my $route = post '/:foo' => {foo => 'bar'} => sub {...}; my $route = post '/:foo' => [foo => qr/\w+/] => sub {...}; my $route = post '/:foo' => (agent => qr/Firefox/) => sub {...}; Generate route with L, matching only C requests. See L and L for more information. =head2 put my $route = put '/:foo' => sub {...}; my $route = put '/:foo' => sub {...} => 'name'; my $route = put '/:foo' => {foo => 'bar'} => sub {...}; my $route = put '/:foo' => [foo => qr/\w+/] => sub {...}; my $route = put '/:foo' => (agent => qr/Firefox/) => sub {...}; Generate route with L, matching only C requests. See L and L for more information. =head2 under my $route = under sub {...}; my $route = under '/:foo' => sub {...}; my $route = under '/:foo' => {foo => 'bar'}; my $route = under '/:foo' => [foo => qr/\w+/]; my $route = under '/:foo' => (agent => qr/Firefox/); my $route = under [format => 0]; Generate nested route with L, to which all following routes are automatically appended. See L and L for more information. =head2 websocket my $route = websocket '/:foo' => sub {...}; my $route = websocket '/:foo' => sub {...} => 'name'; my $route = websocket '/:foo' => {foo => 'bar'} => sub {...}; my $route = websocket '/:foo' => [foo => qr/\w+/] => sub {...}; my $route = websocket '/:foo' => (agent => qr/Firefox/) => sub {...}; Generate route with L, matching only WebSocket handshakes. See L and L for more information. =head1 ATTRIBUTES L inherits all attributes from L. =head1 METHODS L inherits all methods from L. =head1 SEE ALSO L, L, L. =cut