.\" Automatically generated by Pod::Man 2.25 (Pod::Simple 3.16) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is turned on, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .ie \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . nr % 0 . rr F .\} .el \{\ . de IX .. .\} .\" .\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). .\" Fear. Run. Save yourself. No user-serviceable parts. . \" fudge factors for nroff and troff .if n \{\ . ds #H 0 . ds #V .8m . ds #F .3m . ds #[ \f1 . ds #] \fP .\} .if t \{\ . ds #H ((1u-(\\\\n(.fu%2u))*.13m) . ds #V .6m . ds #F 0 . ds #[ \& . ds #] \& .\} . \" simple accents for nroff and troff .if n \{\ . ds ' \& . ds ` \& . ds ^ \& . ds , \& . ds ~ ~ . ds / .\} .if t \{\ . ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" . ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' . ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' . ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' . ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' . ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' .\} . \" troff and (daisy-wheel) nroff accents .ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' .ds 8 \h'\*(#H'\(*b\h'-\*(#H' .ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] .ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' .ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' .ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] .ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] .ds ae a\h'-(\w'a'u*4/10)'e .ds Ae A\h'-(\w'A'u*4/10)'E . \" corrections for vroff .if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' .if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' . \" for low resolution devices (crt and lpr) .if \n(.H>23 .if \n(.V>19 \ \{\ . ds : e . ds 8 ss . ds o a . ds d- d\h'-1'\(ga . ds D- D\h'-1'\(hy . ds th \o'bp' . ds Th \o'LP' . ds ae ae . ds Ae AE .\} .rm #[ #] #H #V #F C .\" ======================================================================== .\" .IX Title "Mojolicious::Lite 3pm" .TH Mojolicious::Lite 3pm "2012-09-05" "perl v5.14.2" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" Mojolicious::Lite \- Real\-time micro web framework .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 2 \& # Automatically enables "strict", "warnings" and Perl 5.10 features \& use Mojolicious::Lite; \& \& # Route with placeholder \& get \*(Aq/:foo\*(Aq => sub { \& my $self = shift; \& my $foo = $self\->param(\*(Aqfoo\*(Aq); \& $self\->render(text => "Hello from $foo."); \& }; \& \& # Start the Mojolicious command system \& app\->start; .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" Mojolicious::Lite is a micro real-time web framework built around Mojolicious. .SH "TUTORIAL" .IX Header "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. .SS "Hello World" .IX Subsection "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. .PP .Vb 2 \& #!/usr/bin/env perl \& use Mojolicious::Lite; \& \& get \*(Aq/\*(Aq => sub { \& my $self = shift; \& $self\->render(text => \*(AqHello World!\*(Aq); \& }; \& \& app\->start; .Ve .SS "Generator" .IX Subsection "Generator" There is also a helper command to generate a small example application. .PP .Vb 1 \& $ mojo generate lite_app .Ve .SS "Commands" .IX Subsection "Commands" All the normal Mojolicious::Commands are available from the command line. Note that \s-1CGI\s0 and \s-1PSGI\s0 environments can usually be auto detected and will just work without commands. .PP .Vb 2 \& $ ./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)... .Ve .SS "Start" .IX Subsection "Start" The app\->start call that starts the Mojolicious command system can be customized to override normal \f(CW@ARGV\fR use. .PP .Vb 1 \& app\->start(\*(Aqcgi\*(Aq); .Ve .SS "Reloading" .IX Subsection "Reloading" Your application will automatically reload itself if you start it with the \&\f(CW\*(C`morbo\*(C'\fR development web server, so you don't have to restart the server after every change. .PP .Vb 2 \& $ morbo myapp.pl \& Server available at http://127.0.0.1:3000. .Ve .SS "Routes" .IX Subsection "Routes" Routes are basically just fancy paths that can contain different kinds of placeholders. \f(CW$self\fR is a Mojolicious::Controller object containing both, the \s-1HTTP\s0 request and response. .PP .Vb 5 \& # /foo \& get \*(Aq/foo\*(Aq => sub { \& my $self = shift; \& $self\->render(text => \*(AqHello World!\*(Aq); \& }; .Ve .SS "\s-1GET/POST\s0 parameters" .IX Subsection "GET/POST parameters" All \f(CW\*(C`GET\*(C'\fR and \f(CW\*(C`POST\*(C'\fR parameters are accessible via \&\*(L"param\*(R" in Mojolicious::Controller. .PP .Vb 6 \& # /foo?user=sri \& get \*(Aq/foo\*(Aq => sub { \& my $self = shift; \& my $user = $self\->param(\*(Aquser\*(Aq); \& $self\->render(text => "Hello $user."); \& }; .Ve .SS "Stash and templates" .IX Subsection "Stash and templates" The \*(L"stash\*(R" in Mojolicious::Controller is used to pass data to templates, which can be inlined in the \f(CW\*(C`DATA\*(C'\fR section. .PP .Vb 6 \& # /bar \& get \*(Aq/bar\*(Aq => sub { \& my $self = shift; \& $self\->stash(one => 23); \& $self\->render(\*(Aqbaz\*(Aq, two => 24); \& }; \& \& _\|_DATA_\|_ \& \& @@ baz.html.ep \& The magic numbers are <%= $one %> and <%= $two %>. .Ve .PP For more information about templates see also \&\*(L"Embedded Perl\*(R" in Mojolicious::Guides::Rendering. .SS "\s-1HTTP\s0" .IX Subsection "HTTP" \&\*(L"req\*(R" in Mojolicious::Controller and \*(L"res\*(R" in Mojolicious::Controller give you full access to all \s-1HTTP\s0 features and information. .PP .Vb 6 \& # /agent \& get \*(Aq/agent\*(Aq => sub { \& my $self = shift; \& $self\->res\->headers\->header(\*(AqX\-Bender\*(Aq => \*(AqBite my shiny metal ass!\*(Aq); \& $self\->render(text => $self\->req\->headers\->user_agent); \& }; .Ve .SS "Route names" .IX Subsection "Route names" All routes can have a name associated with them, this allows automatic template detection and back referencing with \&\*(L"url_for\*(R" in Mojolicious::Controller as well as many helpers like \&\*(L"link_to\*(R" in Mojolicious::Plugin::TagHelpers. Nameless routes get an automatically generated one assigned that is simply equal to the route itself without non-word characters. .PP .Vb 5 \& # / \& get \*(Aq/\*(Aq => sub { \& my $self = shift; \& $self\->render; \& } => \*(Aqindex\*(Aq; \& \& # /hello \& get \*(Aq/hello\*(Aq; \& \& _\|_DATA_\|_ \& \& @@ index.html.ep \& <%= link_to Hello => \*(Aqhello\*(Aq %>. \& <%= link_to Reload => \*(Aqindex\*(Aq %>. \& \& @@ hello.html.ep \& Hello World! .Ve .SS "Layouts" .IX Subsection "Layouts" Templates can have layouts too, you just select one with the helper \&\*(L"layout\*(R" in Mojolicious::Plugin::DefaultHelpers and place the result of the current template with the helper \&\*(L"content\*(R" in Mojolicious::Plugin::DefaultHelpers. .PP .Vb 5 \& # /with_layout \& get \*(Aq/with_layout\*(Aq => sub { \& my $self = shift; \& $self\->render(\*(Aqwith_layout\*(Aq); \& }; \& \& _\|_DATA_\|_ \& \& @@ with_layout.html.ep \& % title \*(AqGreen\*(Aq; \& % layout \*(Aqgreen\*(Aq; \& Hello World! \& \& @@ layouts/green.html.ep \& \& \& <%= title %> \& <%= content %> \& .Ve .SS "Blocks" .IX Subsection "Blocks" Template blocks can be used like normal Perl functions and are always delimited by the \f(CW\*(C`begin\*(C'\fR and \f(CW\*(C`end\*(C'\fR keywords. .PP .Vb 2 \& # /with_block \& get \*(Aq/with_block\*(Aq => \*(Aqblock\*(Aq; \& \& _\|_DATA_\|_ \& \& @@ block.html.ep \& % my $link = begin \& % my ($url, $name) = @_; \& Try <%= link_to $url => begin %><%= $name %><% end %>. \& % end \& \& \& Sebastians frameworks \& \& %= $link\->(\*(Aqhttp://mojolicio.us\*(Aq, \*(AqMojolicious\*(Aq) \& %= $link\->(\*(Aqhttp://catalystframework.org\*(Aq, \*(AqCatalyst\*(Aq) \& \& .Ve .SS "Captured content" .IX Subsection "Captured content" The helper \*(L"content_for\*(R" in Mojolicious::Plugin::TagHelpers can be used to pass around blocks of captured content. .PP .Vb 5 \& # /captured \& get \*(Aq/captured\*(Aq => sub { \& my $self = shift; \& $self\->render(\*(Aqcaptured\*(Aq); \& }; \& \& _\|_DATA_\|_ \& \& @@ captured.html.ep \& % layout \*(Aqblue\*(Aq, title => \*(AqGreen\*(Aq; \& % content_for header => begin \& \& % end \& Hello World! \& % content_for header => begin \& \& % end \& \& @@ layouts/blue.html.ep \& \& \& \& <%= title %> \& %= content_for \*(Aqheader\*(Aq \& \& <%= content %> \& .Ve .SS "Helpers" .IX Subsection "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. .PP .Vb 7 \& # "whois" helper \& helper whois => sub { \& my $self = shift; \& my $agent = $self\->req\->headers\->user_agent || \*(AqAnonymous\*(Aq; \& my $ip = $self\->tx\->remote_address; \& return "$agent ($ip)"; \& }; \& \& # /secret \& get \*(Aq/secret\*(Aq => 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 %>. .Ve .SS "Placeholders" .IX Subsection "Placeholders" Route placeholders allow capturing parts of a request path until a \f(CW\*(C`/\*(C'\fR or \&\f(CW\*(C`.\*(C'\fR separator occurs, results are accessible via \&\*(L"stash\*(R" in Mojolicious::Controller and \*(L"param\*(R" in Mojolicious::Controller. .PP .Vb 7 \& # /foo/test \& # /foo/test123 \& get \*(Aq/foo/:bar\*(Aq => sub { \& my $self = shift; \& my $bar = $self\->stash(\*(Aqbar\*(Aq); \& $self\->render(text => "Our :bar placeholder matched $bar"); \& }; \& \& # /testsomething/foo \& # /test123something/foo \& get \*(Aq/(:bar)something/foo\*(Aq => sub { \& my $self = shift; \& my $bar = $self\->param(\*(Aqbar\*(Aq); \& $self\->render(text => "Our :bar placeholder matched $bar"); \& }; .Ve .SS "Relaxed Placeholders" .IX Subsection "Relaxed Placeholders" Relaxed placeholders allow matching of everything until a \f(CW\*(C`/\*(C'\fR occurs. .PP .Vb 4 \& # /test/hello \& # /test123/hello \& # /test.123/hello \& get \*(Aq/#you/hello\*(Aq => \*(Aqgroovy\*(Aq; \& \& _\|_DATA_\|_ \& \& @@ groovy.html.ep \& Your name is <%= $you %>. .Ve .SS "Wildcard placeholders" .IX Subsection "Wildcard placeholders" Wildcard placeholders allow matching absolutely everything, including \f(CW\*(C`/\*(C'\fR and \&\f(CW\*(C`.\*(C'\fR. .PP .Vb 4 \& # /hello/test \& # /hello/test123 \& # /hello/test.123/test/123 \& get \*(Aq/hello/*you\*(Aq => \*(Aqgroovy\*(Aq; \& \& _\|_DATA_\|_ \& \& @@ groovy.html.ep \& Your name is <%= $you %>. .Ve .SS "\s-1HTTP\s0 methods" .IX Subsection "HTTP methods" Routes can be restricted to specific request methods. .PP .Vb 5 \& # GET /hello \& get \*(Aq/hello\*(Aq => sub { \& my $self = shift; \& $self\->render(text => \*(AqHello World!\*(Aq); \& }; \& \& # PUT /hello \& put \*(Aq/hello\*(Aq => 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)] => \*(Aq/bye\*(Aq => sub { \& my $self = shift; \& $self\->render(text => \*(AqBye World!\*(Aq); \& }; \& \& # * /whatever \& any \*(Aq/whatever\*(Aq => sub { \& my $self = shift; \& my $method = $self\->req\->method; \& $self\->render(text => "You called /whatever with $method."); \& }; .Ve .SS "Optional placeholders" .IX Subsection "Optional placeholders" Routes allow default values to make placeholders optional. .PP .Vb 6 \& # /hello \& # /hello/Sara \& get \*(Aq/hello/:name\*(Aq => {name => \*(AqSebastian\*(Aq} => sub { \& my $self = shift; \& $self\->render(\*(Aqgroovy\*(Aq, format => \*(Aqtxt\*(Aq); \& }; \& \& _\|_DATA_\|_ \& \& @@ groovy.txt.ep \& My name is <%= $name %>. .Ve .SS "Restrictive placeholders" .IX Subsection "Restrictive placeholders" The easiest way to make placeholders more restrictive are alternatives, you just make a list of possible values. .PP .Vb 7 \& # /test \& # /123 \& any \*(Aq/:foo\*(Aq => [foo => [qw(test 123)]] => sub { \& my $self = shift; \& my $foo = $self\->param(\*(Aqfoo\*(Aq); \& $self\->render(text => "Our :foo placeholder matched $foo"); \& }; .Ve .PP All placeholders get compiled to a regex internally, this process can also be easily customized. .PP .Vb 7 \& # /1 \& # /123 \& any \*(Aq/:bar\*(Aq => [bar => qr/\ed+/] => sub { \& my $self = shift; \& my $bar = $self\->param(\*(Aqbar\*(Aq); \& $self\->render(text => "Our :bar placeholder matched $bar"); \& }; .Ve .PP Just make sure not to use \f(CW\*(C`^\*(C'\fR and \f(CW\*(C`$\*(C'\fR or capturing groups \f(CW\*(C`(...)\*(C'\fR, because placeholders become part of a larger regular expression internally, \f(CW\*(C`(?:...)\*(C'\fR is fine though. .SS "Under" .IX Subsection "Under" Authentication and code shared between multiple routes can be realized easily with the \f(CW\*(C`under\*(C'\fR statement. All following routes are only evaluated if the \&\f(CW\*(C`under\*(C'\fR callback returned a true value. .PP .Vb 1 \& use Mojolicious::Lite; \& \& # Authenticate based on name parameter \& under sub { \& my $self = shift; \& \& # Authenticated \& my $name = $self\->param(\*(Aqname\*(Aq) || \*(Aq\*(Aq; \& return 1 if $name eq \*(AqBender\*(Aq; \& \& # Not authenticated \& $self\->render(\*(Aqdenied\*(Aq); \& return; \& }; \& \& # / (with authentication) \& get \*(Aq/\*(Aq => \*(Aqindex\*(Aq; \& \& app\->start; \& _\|_DATA_\|_; \& \& @@ denied.html.ep \& You are not Bender, permission denied. \& \& @@ index.html.ep \& Hi Bender. .Ve .PP Prefixing multiple routes is another good use for \f(CW\*(C`under\*(C'\fR. .PP .Vb 1 \& use Mojolicious::Lite; \& \& # /foo \& under \*(Aq/foo\*(Aq; \& \& # /foo/bar \& get \*(Aq/bar\*(Aq => {text => \*(Aqfoo bar\*(Aq}; \& \& # /foo/baz \& get \*(Aq/baz\*(Aq => {text => \*(Aqfoo baz\*(Aq}; \& \& # / \& under \*(Aq/\*(Aq => {message => \*(Aqwhatever\*(Aq}; \& \& # /bar \& get \*(Aq/bar\*(Aq => {inline => \*(Aq<%= $message %> works\*(Aq}; \& \& app\->start; .Ve .PP You can also \f(CW\*(C`group\*(C'\fR related routes, which allows nesting of multiple \&\f(CW\*(C`under\*(C'\fR statements. .PP .Vb 1 \& use Mojolicious::Lite; \& \& # Global logic shared by all routes \& under sub { \& my $self = shift; \& return 1 if $self\->req\->headers\->header(\*(AqX\-Bender\*(Aq); \& $self\->render(text => "You\*(Aqre not Bender."); \& return; \& }; \& \& # Admin section \& group { \& \& # Local logic shared only by routes in this group \& under \*(Aq/admin\*(Aq => sub { \& my $self = shift; \& return 1 if $self\->req\->heaers\->header(\*(AqX\-Awesome\*(Aq); \& $self\->render(text => "You\*(Aqre not awesome enough."); \& return; \& }; \& \& # GET /admin/dashboard \& get \*(Aq/dashboard\*(Aq => {text => \*(AqNothing to see here yet.\*(Aq}; \& }; \& \& # GET /welcome \& get \*(Aq/welcome\*(Aq => {text => \*(AqHi Bender.\*(Aq}; \& \& app\->start; .Ve .SS "Formats" .IX Subsection "Formats" Formats can be automatically detected by looking at file extensions. .PP .Vb 6 \& # /detection.html \& # /detection.txt \& get \*(Aq/detection\*(Aq => sub { \& my $self = shift; \& $self\->render(\*(Aqdetected\*(Aq); \& }; \& \& _\|_DATA_\|_ \& \& @@ detected.html.ep \& \& \& Detected \& HTML was detected. \& \& \& @@ detected.txt.ep \& TXT was detected. .Ve .PP Restrictive placeholders can also be used. .PP .Vb 8 \& # /hello.json \& # /hello.txt \& get \*(Aq/hello\*(Aq => [format => [qw(json txt)]] => sub { \& my $self = shift; \& return $self\->render_json({hello => \*(Aqworld\*(Aq}) \& if $self\->stash(\*(Aqformat\*(Aq) eq \*(Aqjson\*(Aq; \& $self\->render_text(\*(Aqhello world\*(Aq); \& }; .Ve .PP Or you can just disable format detection. .PP .Vb 2 \& # /hello \& get \*(Aq/hello\*(Aq => [format => 0] => {text => \*(AqNo format detection.\*(Aq}; \& \& # Disable detection and allow the following routes selective re\-enabling \& under [format => 0]; \& \& # /foo \& get \*(Aq/foo\*(Aq => {text => \*(AqNo format detection again.\*(Aq}; \& \& # /bar.txt \& get \*(Aq/bar\*(Aq => [format => \*(Aqtxt\*(Aq] => {text => \*(Aq Just one format.\*(Aq}; .Ve .SS "Content negotiation" .IX Subsection "Content negotiation" For resources with different representations and that require truly \f(CW\*(C`RESTful\*(C'\fR content negotiation you can also use \*(L"respond_to\*(R" in Mojolicious::Controller. .PP .Vb 10 \& # /hello (Accept: application/json) \& # /hello (Accept: text/xml) \& # /hello.json \& # /hello.xml \& # /hello?format=json \& # /hello?format=xml \& get \*(Aq/hello\*(Aq => sub { \& my $self = shift; \& $self\->respond_to( \& json => {json => {hello => \*(Aqworld\*(Aq}}, \& xml => {text => \*(Aqworld\*(Aq}, \& any => {data => \*(Aq\*(Aq, status => 204} \& ); \& }; .Ve .PP \&\s-1MIME\s0 type mappings can be extended or changed easily with \&\*(L"types\*(R" in Mojolicious. .PP .Vb 1 \& app\->types\->type(rdf => \*(Aqapplication/rdf+xml\*(Aq); .Ve .SS "Conditions" .IX Subsection "Conditions" Conditions such as \f(CW\*(C`agent\*(C'\fR and \f(CW\*(C`host\*(C'\fR from Mojolicious::Plugin::HeaderCondition allow even more powerful route constructs. .PP .Vb 5 \& # /foo (Firefox) \& get \*(Aq/foo\*(Aq => (agent => qr/Firefox/) => sub { \& my $self = shift; \& $self\->render(text => \*(AqCongratulations, you are using a cool browser.\*(Aq); \& }; \& \& # /foo (Internet Explorer) \& get \*(Aq/foo\*(Aq => (agent => qr/Internet Explorer/) => sub { \& my $self = shift; \& $self\->render(text => \*(AqDude, you really need to upgrade to Firefox.\*(Aq); \& }; \& \& # http://mojolicio.us/bar \& get \*(Aq/bar\*(Aq => (host => \*(Aqmojolicio.us\*(Aq) => sub { \& my $self = shift; \& $self\->render(text => \*(AqHello Mojolicious.\*(Aq); \& }; .Ve .SS "Sessions" .IX Subsection "Sessions" Signed cookie based sessions just work out of the box as soon as you start using them through the helper \&\*(L"session\*(R" in Mojolicious::Plugin::DefaultHelpers. .PP .Vb 1 \& use Mojolicious::Lite; \& \& get \*(Aq/counter\*(Aq => sub { \& my $self = shift; \& $self\->session\->{counter}++; \& }; \& \& app\->start; \& _\|_DATA_\|_ \& \& @@ counter.html.ep \& Counter: <%= session \*(Aqcounter\*(Aq %> .Ve .SS "Secret" .IX Subsection "Secret" Note that you should use a custom \*(L"secret\*(R" in Mojolicious to make signed cookies really secure. .PP .Vb 1 \& app\->secret(\*(AqMy secret passphrase here\*(Aq); .Ve .SS "File uploads" .IX Subsection "File uploads" All files uploaded via \f(CW\*(C`multipart/form\-data\*(C'\fR request are automatically available as Mojo::Upload objects. And you don't have to worry about memory usage, because all files above \f(CW\*(C`250KB\*(C'\fR will be automatically streamed into a temporary file. .PP .Vb 1 \& use Mojolicious::Lite; \& \& # Upload form in DATA section \& get \*(Aq/\*(Aq => \*(Aqform\*(Aq; \& \& # Multipart upload handler \& post \*(Aq/upload\*(Aq => sub { \& my $self = shift; \& \& # Check file size \& return $self\->render(text => \*(AqFile is too big.\*(Aq, status => 200) \& if $self\->req\->is_limit_exceeded; \& \& # Process uploaded file \& return $self\->redirect_to(\*(Aqform\*(Aq) \& unless my $example = $self\->param(\*(Aqexample\*(Aq); \& my $size = $example\->size; \& my $name = $example\->filename; \& $self\->render(text => "Thanks for uploading $size byte file $name."); \& }; \& \& app\->start; \& _\|_DATA_\|_ \& \& @@ form.html.ep \& \& \& Upload \& \& %= form_for upload => (enctype => \*(Aqmultipart/form\-data\*(Aq) => begin \& %= file_field \*(Aqexample\*(Aq \& %= submit_button \*(AqUpload\*(Aq \& % end \& \& .Ve .PP To protect you from excessively large files there is also a limit of \f(CW\*(C`5MB\*(C'\fR by default, which you can tweak with the \f(CW\*(C`MOJO_MAX_MESSAGE_SIZE\*(C'\fR environment variable. .PP .Vb 2 \& # Increase limit to 1GB \& $ENV{MOJO_MAX_MESSAGE_SIZE} = 1073741824; .Ve .SS "User agent" .IX Subsection "User agent" With \*(L"ua\*(R" in Mojolicious::Controller there's a full featured \s-1HTTP\s0 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. .PP .Vb 4 \& get \*(Aq/test\*(Aq => sub { \& my $self = shift; \& $self\->render(data => $self\->ua\->get(\*(Aqhttp://mojolicio.us\*(Aq)\->res\->body); \& }; .Ve .SS "WebSockets" .IX Subsection "WebSockets" WebSocket applications have never been this easy before. .PP .Vb 7 \& websocket \*(Aq/echo\*(Aq => sub { \& my $self = shift; \& $self\->on(message => sub { \& my ($self, $message) = @_; \& $self\->send("echo: $message"); \& }); \& }; .Ve .PP The event \*(L"message\*(R" in Mojo::Transaction::WebSocket, which you can subscribe to with \*(L"on\*(R" in Mojolicious::Controller, will be emitted for every new WebSocket message that is received. .SS "External templates" .IX Subsection "External templates" External templates will be searched by the renderer in a \f(CW\*(C`templates\*(C'\fR directory. .PP .Vb 3 \& # /external \& any \*(Aq/external\*(Aq => sub { \& my $self = shift; \& \& # templates/foo/bar.html.ep \& $self\->render(\*(Aqfoo/bar\*(Aq); \& }; .Ve .SS "Static files" .IX Subsection "Static files" Static files will be automatically served from the \f(CW\*(C`DATA\*(C'\fR section (even Base64 encoded) or a \f(CW\*(C`public\*(C'\fR directory if it exists. .PP .Vb 2 \& @@ something.js \& alert(\*(Aqhello!\*(Aq); \& \& @@ test.txt (base64) \& dGVzdCAxMjMKbGFsYWxh \& \& $ mkdir public \& $ mv something.js public/something.js .Ve .SS "Testing" .IX Subsection "Testing" Testing your application is as easy as creating a \f(CW\*(C`t\*(C'\fR directory and filling it with normal Perl unit tests. .PP .Vb 2 \& use Test::More tests => 3; \& use Test::Mojo; \& \& use FindBin; \& require "$FindBin::Bin/../myapp.pl"; \& \& my $t = Test::Mojo\->new; \& $t\->get_ok(\*(Aq/\*(Aq)\->status_is(200)\->content_like(qr/Funky/); .Ve .PP Run all unit tests with the \f(CW\*(C`test\*(C'\fR command. .PP .Vb 1 \& $ ./myapp.pl test .Ve .PP 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. .PP .Vb 1 \& $t\->app\->log\->level(\*(Aqdebug\*(Aq); .Ve .SS "Mode" .IX Subsection "Mode" To disable debug messages later in a production setup you can change the Mojolicious mode, default will be \f(CW\*(C`development\*(C'\fR. .PP .Vb 1 \& $ ./myapp.pl \-m production .Ve .SS "Logging" .IX Subsection "Logging" Mojo::Log messages will be automatically written to \f(CW\*(C`STDERR\*(C'\fR or a \&\f(CW\*(C`log/$mode.log\*(C'\fR file if a \f(CW\*(C`log\*(C'\fR directory exists. .PP .Vb 1 \& $ mkdir log .Ve .PP For more control the Mojolicious object can be accessed directly. .PP .Vb 6 \& app\->log\->level(\*(Aqerror\*(Aq); \& app\->routes\->get(\*(Aq/foo/:bar\*(Aq => sub { \& my $self = shift; \& $self\->app\->log\->debug(\*(AqGot a request for "Hello Mojo!".\*(Aq); \& $self\->render(text => \*(AqHello Mojo!\*(Aq); \& }); .Ve .SS "More" .IX Subsection "More" You can continue with Mojolicious::Guides now, and don't forget to have fun! .SH "FUNCTIONS" .IX Header "FUNCTIONS" Mojolicious::Lite implements the following functions. .ie n .SS """any""" .el .SS "\f(CWany\fP" .IX Subsection "any" .Vb 2 \& my $route = any \*(Aq/:foo\*(Aq => sub {...}; \& my $route = any [qw(GET POST)] => \*(Aq/:foo\*(Aq => sub {...}; .Ve .PP Generate route with \*(L"any\*(R" in Mojolicious::Routes::Route, matching any of the listed \s-1HTTP\s0 request methods or all. See also the tutorial above for more argument variations. .ie n .SS """app""" .el .SS "\f(CWapp\fP" .IX Subsection "app" .Vb 1 \& my $app = app; .Ve .PP The Mojolicious::Lite application. .ie n .SS """del""" .el .SS "\f(CWdel\fP" .IX Subsection "del" .Vb 1 \& my $route = del \*(Aq/:foo\*(Aq => sub {...}; .Ve .PP Generate route with \*(L"delete\*(R" in Mojolicious::Routes::Route, matching only \&\f(CW\*(C`DELETE\*(C'\fR requests. See also the tutorial above for more argument variations. .ie n .SS """get""" .el .SS "\f(CWget\fP" .IX Subsection "get" .Vb 1 \& my $route = get \*(Aq/:foo\*(Aq => sub {...}; .Ve .PP Generate route with \*(L"get\*(R" in Mojolicious::Routes::Route, matching only \f(CW\*(C`GET\*(C'\fR requests. See also the tutorial above for more argument variations. .ie n .SS """group""" .el .SS "\f(CWgroup\fP" .IX Subsection "group" .Vb 1 \& group {...}; .Ve .PP Start a new route group. .ie n .SS """helper""" .el .SS "\f(CWhelper\fP" .IX Subsection "helper" .Vb 1 \& helper foo => sub {...}; .Ve .PP Alias for \*(L"helper\*(R" in Mojolicious. .ie n .SS """hook""" .el .SS "\f(CWhook\fP" .IX Subsection "hook" .Vb 1 \& hook after_dispatch => sub {...}; .Ve .PP Alias for \*(L"hook\*(R" in Mojolicious. .ie n .SS """options""" .el .SS "\f(CWoptions\fP" .IX Subsection "options" .Vb 1 \& my $route = options \*(Aq/:foo\*(Aq => sub {...}; .Ve .PP Generate route with \*(L"options\*(R" in Mojolicious::Routes::Route, matching only \&\f(CW\*(C`OPTIONS\*(C'\fR requests. See also the tutorial above for more argument variations. .ie n .SS """patch""" .el .SS "\f(CWpatch\fP" .IX Subsection "patch" .Vb 1 \& my $route = patch \*(Aq/:foo\*(Aq => sub {...}; .Ve .PP Generate route with \*(L"patch\*(R" in Mojolicious::Routes::Route, matching only \&\f(CW\*(C`PATCH\*(C'\fR requests. See also the tutorial above for more argument variations. .ie n .SS """plugin""" .el .SS "\f(CWplugin\fP" .IX Subsection "plugin" .Vb 1 \& plugin \*(AqSomeThing\*(Aq; .Ve .PP Alias for \*(L"plugin\*(R" in Mojolicious. .ie n .SS """post""" .el .SS "\f(CWpost\fP" .IX Subsection "post" .Vb 1 \& my $route = post \*(Aq/:foo\*(Aq => sub {...}; .Ve .PP Generate route with \*(L"post\*(R" in Mojolicious::Routes::Route, matching only \&\f(CW\*(C`POST\*(C'\fR requests. See also the tutorial above for more argument variations. .ie n .SS """put""" .el .SS "\f(CWput\fP" .IX Subsection "put" .Vb 1 \& my $route = put \*(Aq/:foo\*(Aq => sub {...}; .Ve .PP Generate route with \*(L"put\*(R" in Mojolicious::Routes::Route, matching only \f(CW\*(C`PUT\*(C'\fR requests. See also the tutorial above for more argument variations. .ie n .SS """under""" .el .SS "\f(CWunder\fP" .IX Subsection "under" .Vb 2 \& my $route = under sub {...}; \& my $route = under \*(Aq/:foo\*(Aq; .Ve .PP Generate bridge with \*(L"under\*(R" in Mojolicious::Routes::Route, to which all following routes are automatically appended. See also the tutorial above for more argument variations. .ie n .SS """websocket""" .el .SS "\f(CWwebsocket\fP" .IX Subsection "websocket" .Vb 1 \& my $route = websocket \*(Aq/:foo\*(Aq => sub {...}; .Ve .PP Generate route with \*(L"websocket\*(R" in Mojolicious::Routes::Route, matching only \&\f(CW\*(C`WebSocket\*(C'\fR handshakes. See also the tutorial above for more argument variations. .SH "ATTRIBUTES" .IX Header "ATTRIBUTES" Mojolicious::Lite inherits all attributes from Mojolicious. .SH "METHODS" .IX Header "METHODS" Mojolicious::Lite inherits all methods from Mojolicious. .SH "SEE ALSO" .IX Header "SEE ALSO" Mojolicious, Mojolicious::Guides, .