1Mojolicious::Lite(3) User Contributed Perl Documentation Mojolicious::Lite(3)
2
3
4
6 Mojolicious::Lite - Micro Web Framework
7
9 # Using Mojolicious::Lite will enable "strict" and "warnings"
10 use Mojolicious::Lite;
11
12 # Route with placeholder
13 get '/:foo' => sub {
14 my $self = shift;
15 my $foo = $self->param('foo');
16 $self->render(text => "Hello from $foo!");
17 };
18
19 # Start the Mojolicious command system
20 app->start;
21
23 Mojolicous::Lite is a micro web framework built around Mojolicious.
24
25 A minimal Hello World application looks like this, strict and warnings
26 are automatically enabled and a few functions imported when you use
27 Mojolicious::Lite, turning your script into a full featured web
28 application.
29
30 #!/usr/bin/env perl
31
32 use Mojolicious::Lite;
33
34 get '/' => sub { shift->render(text => 'Hello World!') };
35
36 app->start;
37
38 There is also a helper command to generate a small example application.
39
40 % mojolicious generate lite_app
41
42 All the normal Mojolicious command options are available from the
43 command line. Note that CGI, FastCGI and PSGI environments can usually
44 be auto detected and will just work without commands.
45
46 % ./myapp.pl daemon
47 Server available at http://127.0.0.1:3000.
48
49 % ./myapp.pl daemon --listen http://*:8080
50 Server available at http://127.0.0.1:8080.
51
52 % ./myapp.pl daemon_prefork
53 Server available at http://127.0.0.1:3000.
54
55 % ./myapp.pl cgi
56 ...CGI output...
57
58 % ./myapp.pl fastcgi
59 ...Blocking FastCGI main loop...
60
61 % ./myapp.pl
62 ...List of available commands (or automatically detected environment)...
63
64 The app->start call that starts the Mojolicious command system can be
65 customized to override normal @ARGV use.
66
67 app->start('cgi');
68
69 Your application will automatically reload itself if you set the
70 "--reload" option, so you don't have to restart the server after every
71 change.
72
73 % ./myapp.pl daemon --reload
74 Server available at http://127.0.0.1:3000.
75
76 Routes are basically just fancy paths that can contain different kinds
77 of placeholders.
78
79 # /foo
80 get '/foo' => sub {
81 my $self = shift;
82 $self->render(text => 'Hello World!');
83 };
84
85 All routes can have a name associated with them, this allows automatic
86 template detection and back referencing with "url_for", "link_to" and
87 "form_for". Names are always the last argument, the value "*" means
88 that the name is simply equal to the route without non-word characters.
89
90 # /
91 get '/' => 'index';
92
93 # /foo
94 get '/foo' => '*';
95
96 # /bar
97 get '/bar' => sub {
98 my $self = shift;
99 $self->render(text => 'Hi!')
100 } => 'bar';
101
102 __DATA__
103
104 @@ index.html.ep
105 <%= link_to foo => {%>
106 Foo
107 <%}%>.
108 <%= link_to bar => {%>
109 Bar
110 <%}%>.
111
112 @@ foo.html.ep
113 <a href="<%= url_for 'index' %>">Home</a>.
114
115 Templates can have layouts.
116
117 # GET /with_layout
118 get '/with_layout' => sub {
119 my $self = shift;
120 $self->render('with_layout', layout => 'green');
121 };
122
123 __DATA__
124
125 @@ with_layout.html.ep
126 We've got content!
127
128 @@ layouts/green.html.ep
129 <!doctype html><html>
130 <head><title>Green!</title></head>
131 <body><%= content %></body>
132 </html>
133
134 Template blocks can be reused like functions in Perl scripts.
135
136 # GET /with_block
137 get '/with_block' => 'block';
138
139 __DATA__
140
141 @@ block.html.ep
142 <% my $link = {%>
143 <% my ($url, $name) = @_; %>
144 Try <%= link_to $url => {%><%= $name %><%}%>!
145 <%}%>
146 <!doctype html><html>
147 <head><title>Sebastians Frameworks!</title></head>
148 <body>
149 <%== $link->('http://mojolicious.org', 'Mojolicious') %>
150 <%== $link->('http://catalystframework.org', 'Catalyst') %>
151 </body>
152 </html>
153
154 Templates can also pass around blocks of captured content and extend
155 each other.
156
157 # GET /
158 get '/' => 'first';
159
160 # GET /second
161 get '/second' => 'second';
162
163 __DATA__
164
165 @@ first.html.ep
166 <!doctype html><html>
167 <head><%= content header => {%><title>Hi!</title><%}%></head>
168 <body><%= content body => {%>First page!<%}%></body>
169 </html>
170
171 @@ second.html.ep
172 % extends 'first';
173 <% content header => {%>
174 <title>Howdy!</title>
175 <%}%>
176 <% content body => {%>
177 Second page!
178 <%}%>
179
180 Route placeholders allow capturing parts of a request path until a "/"
181 or "." separator occurs, results will be stored by name in the "stash"
182 and "param".
183
184 # /foo/* (everything except "/" and ".")
185 # /foo/test
186 # /foo/test123
187 get '/foo/:bar' => sub {
188 my $self = shift;
189 my $bar = $self->stash('bar');
190 $self->render(text => "Our :bar placeholder matched $bar");
191 };
192
193 # /*something/foo (everything except "/" and ".")
194 # /test/foo
195 # /test123/foo
196 get '/(:bar)something/foo' => sub {
197 my $self = shift;
198 my $bar = $self->param('bar');
199 $self->render(text => "Our :bar placeholder matched $bar");
200 };
201
202 Relaxed placeholders allow matching of everything until a "/" occurs.
203
204 # /*/hello (everything except "/")
205 # /test/hello
206 # /test123/hello
207 # /test.123/hello
208 get '/(.you)/hello' => sub {
209 shift->render('groovy');
210 };
211
212 __DATA__
213
214 @@ groovy.html.ep
215 Your name is <%= $you %>.
216
217 Wildcard placeholders allow matching absolutely everything, including
218 "/" and ".".
219
220 # /hello/* (everything)
221 # /hello/test
222 # /hello/test123
223 # /hello/test.123/test/123
224 get '/hello/(*you)' => sub {
225 shift->render('groovy');
226 };
227
228 __DATA__
229
230 @@ groovy.html.ep
231 Your name is <%= $you %>.
232
233 Routes can be restricted to specific request methods.
234
235 # GET /bye
236 get '/bye' => sub { shift->render(text => 'Bye!') };
237
238 # POST /bye
239 post '/bye' => sub { shift->render(text => 'Bye!') };
240
241 # GET|POST|DELETE /bye
242 any [qw/get post delete/] => '/bye' => sub {
243 shift->render(text => 'Bye!');
244 };
245
246 # /baz
247 any '/baz' => sub {
248 my $self = shift;
249 my $method = $self->req->method;
250 $self->render(text => "You called /baz with $method");
251 };
252
253 All placeholders get compiled to a regex internally, with regex
254 constraints this process can be easily customized.
255
256 # /*
257 any '/:bar' => [bar => qr/\d+/] => sub {
258 my $self = shift;
259 my $bar = $self->param('bar');
260 $self->render(text => "Our :bar placeholder matched $bar");
261 };
262
263 Routes allow default values to make placeholders optional.
264
265 # /hello/*
266 get '/hello/:name' => {name => 'Sebastian'} => sub {
267 my $self = shift;
268 $self->render('groovy', format => 'txt');
269 };
270
271 __DATA__
272
273 @@ groovy.txt.ep
274 My name is <%= $name %>.
275
276 All those features can be easily used together.
277
278 # /everything/*?name=*
279 get '/everything/:stuff' => [stuff => qr/\d+/] => {stuff => 23} => sub {
280 shift->render('welcome');
281 };
282
283 __DATA__
284
285 @@ welcome.html.ep
286 Stuff is <%= $stuff %>.
287 Query param name is <%= param 'name' %>.
288
289 Here's a fully functional example for a html form handling application
290 using multiple features at once.
291
292 #!/usr/bin/env perl
293
294 use Mojolicious::Lite;
295
296 get '/' => 'index';
297
298 post '/test' => sub {
299 my $self = shift;
300
301 my $groovy = $self->param('groovy') || 'Austin Powers';
302 $groovy =~ s/[^\w\s]+//g;
303
304 $self->render(
305 template => 'welcome',
306 layout => 'funky',
307 groovy => $groovy
308 );
309 } => 'test';
310
311 app->start;
312 __DATA__
313
314 @@ index.html.ep
315 % layout 'funky';
316 Who is groovy?
317 <%= form_for test => (method => 'post') => {%>
318 <%= input 'groovy', type => 'text' %>
319 <input type="submit" value="Woosh!" />
320 <%}%>
321
322 @@ welcome.html.ep
323 <%= $groovy %> is groovy!
324 <%= include 'menu' %>
325
326 @@ menu.html.ep
327 <%= link_to index => {%>
328 Try again
329 <%}%>
330
331 @@ layouts/funky.html.ep
332 <!doctype html><html>
333 <head><title>Funky!</title></head>
334 <body><%= content %>
335 </body>
336 </html>
337
338 Authentication and code shared between multiple routes can be realized
339 easily with the "under" statement. All following routes are only
340 evaluated if the "under" callback returned a true value.
341
342 use Mojolicious::Lite;
343
344 # Authenticate based on name parameter
345 under sub {
346 my $self = shift;
347
348 # Authenticated
349 my $name = $self->param('name') || '';
350 return 1 if $name eq 'Bender';
351
352 # Not authenticated
353 $self->render('denied');
354 return;
355 };
356
357 # GET / (with authentication)
358 get '/' => 'index';
359
360 app->start;
361 __DATA__;
362
363 @@ denied.html.ep
364 You are not Bender, permission denied!
365
366 @@ index.html.ep
367 Hi Bender!
368
369 Conditions such as "agent" allow even more powerful route constructs.
370
371 # /foo
372 get '/foo' => (agent => qr/Firefox/) => sub {
373 shift->render(
374 text => 'Congratulations, you are using a cool browser!');
375 }
376
377 # /foo
378 get '/foo' => (agent => qr/Internet Explorer/) => sub {
379 shift->render(
380 text => 'Dude, you really need to upgrade to Firefox!');
381 }
382
383 Formats can be automatically detected by looking at file extensions.
384
385 # /detection.html
386 # /detection.txt
387 get '/detection' => sub {
388 my $self = shift;
389 $self->render('detected');
390 };
391
392 __DATA__
393
394 @@ detected.html.ep
395 <!doctype html><html>
396 <head><title>Detected!</title></head>
397 <body>HTML was detected.</body>
398 </html>
399
400 @@ detected.txt.ep
401 TXT was detected.
402
403 Signed cookie based sessions just work out of the box as soon as you
404 start using them. The "flash" can be used to store values that will
405 only be available for one request, this is very useful in combination
406 with "redirect_to".
407
408 use Mojolicious::Lite;
409
410 get '/login' => sub {
411 my $self = shift;
412 my $name = $self->param('name') || '';
413 my $pass = $self->param('pass') || '';
414 return $self->render unless $name eq 'sebastian' && $pass eq '1234';
415 $self->session(name => $name);
416 $self->flash(message => 'Thanks for logging in!');
417 $self->redirect_to('index');
418 } => 'login';
419
420 get '/' => sub {
421 my $self = shift;
422 return $self->redirect_to('login') unless $self->session('name');
423 $self->render;
424 } => 'index';
425
426 get '/logout' => sub {
427 my $self = shift;
428 $self->session(expires => 1);
429 $self->redirect_to('index');
430 } => 'logout';
431
432 app->start;
433 __DATA__
434
435 @@ layouts/default.html.ep
436 <!doctype html><html>
437 <head><title>Mojolicious rocks!</title></head>
438 <body><%= content %></body>
439 </html>
440
441 @@ login.html.ep
442 % layout 'default';
443 <%= form_for login => {%>
444 <% if (param 'name') { %>
445 <b>Wrong name or password, please try again.</b><br />
446 <% } %>
447 Name:<br />
448 <%= input name => (type => 'text') %><br />
449 Password:<br />
450 <%= input pass => (type => 'text') %><br />
451 <input type="submit" value="Login" />
452 <%}%>
453
454 @@ index.html.ep
455 % layout 'default';
456 <% if (my $message = flash 'message' ) { %>
457 <b><%= $message %></b><br />
458 <% } %>
459 Welcome <%= session 'name' %>!<br />
460 <%= link_to logout => {%>
461 Logout
462 <%}%>
463
464 Note that you should use a custom "secret" to make signed cookies
465 really secure.
466
467 app->secret('My secret passphrase here!');
468
469 A full featured HTTP 1.1 and WebSocket client is built right in.
470 Especially in combination with Mojo::JSON and Mojo::DOM this can be a
471 very powerful tool.
472
473 get '/test' => sub {
474 my $self = shift;
475 $self->render(
476 data => $self->client->get('http://mojolicious.org')->res->body);
477 };
478
479 WebSocket applications have never been this easy before.
480
481 websocket '/echo' => sub {
482 my $self = shift;
483 $self->receive_message(sub {
484 my ($self, $message) = @_;
485 $self->send_message("echo: $message");
486 });
487 };
488
489 External templates will be searched by the renderer in a "templates"
490 directory.
491
492 # /external
493 any '/external' => sub {
494 my $self = shift;
495
496 # templates/foo/bar.html.ep
497 $self->render('foo/bar');
498 };
499
500 Static files will be automatically served from the "DATA" section (even
501 Base 64 encoded) or a "public" directory if it exists.
502
503 @@ something.js
504 alert('hello!');
505
506 @@ test.txt (base64)
507 dGVzdCAxMjMKbGFsYWxh
508
509 % mkdir public
510 % mv something.js public/something.js
511
512 Testing your application is as easy as creating a "t" directory and
513 filling it with normal Perl unit tests like "t/funky.t".
514
515 use Test::More tests => 3;
516 use Test::Mojo;
517
518 use FindBin;
519 $ENV{MOJO_HOME} = "$FindBin::Bin/../";
520 require "$ENV{MOJO_HOME}/myapp.pl";
521
522 my $t = Test::Mojo->new;
523 $t->get_ok('/')->status_is(200)->content_like(qr/Funky!/);
524
525 Run all unit tests with the "test" command.
526
527 % ./myapp.pl test
528
529 To make your tests less noisy you can also change the application log
530 level directly in your test files.
531
532 $t->app->log->level('error');
533
534 To disable debug messages later in a production setup you can change
535 the Mojolicious mode, default will be "development".
536
537 % MOJO_MODE=production ./myapp.pl
538
539 Log messages will be automatically written to a "log/$mode.log" file if
540 a "log" directory exists.
541
542 % mkdir log
543
544 For more control the Mojolicious instance can be accessed directly.
545
546 app->log->level('error');
547 app->routes->route('/foo/:bar')->via('get')->to(cb => sub {
548 my $self = shift;
549 $self->render(text => 'Hello Mojo!');
550 });
551
552 In case a lite app needs to grow, lite and real Mojolicous applications
553 can be easily mixed to make the transition process very smooth.
554
555 package MyApp::Foo;
556 use base 'Mojolicious::Controller';
557
558 sub index { shift->render(text => 'It works!') }
559
560 package main;
561 use Mojolicious::Lite;
562
563 get '/bar' => sub { shift->render(text => 'This too!') };
564
565 app->routes->namespace('MyApp');
566 app->routes->route('/foo/:action')->via('get')->to('foo#index');
567
568 app->start;
569
570 There is also a helper command to generate a full Mojolicious example
571 that will let you explore the astonishing similarities between
572 Mojolicious::Lite and Mojolicious applications. Both share about 99%
573 of the same code, so almost everything you learned in this tutorial
574 applies there too. :)
575
576 % mojolicious generate app
577
578 Have fun!
579
581 Mojolicious::Lite inherits all attributes from Mojolicious.
582
584 Mojolicious::Lite inherits all methods from Mojolicious.
585
587 Mojolicious, Mojolicious::Guides, <http://mojolicious.org>.
588
589
590
591perl v5.12.3 2010-08-14 Mojolicious::Lite(3)