source: main/trunk/greenstone2/perllib/cpan/Mojolicious/Guides/Tutorial.pod@ 32205

Last change on this file since 32205 was 32205, checked in by ak19, 6 years ago

First set of commits to do with implementing the new 'paged_html' output option of PDFPlugin that uses using xpdftools' new pdftohtml. So far tested only on Linux (64 bit), but things work there so I'm optimistically committing the changes since they work. 2. Committing the pre-built Linux binaries of XPDFtools for both 32 and 64 bit built by the XPDF group. 2. To use the correct bitness variant of xpdftools, setup.bash now exports the BITNESS env var, consulted by gsConvert.pl. 3. All the perl code changes to do with using xpdf tools' pdftohtml to generate paged_html and feed it in the desired form into GS(3): gsConvert.pl, PDFPlugin.pm and its parent ConvertBinaryPFile.pm have been modified to make it all work. xpdftools' pdftohtml generates a folder containing an html file and a screenshot for each page in a PDF (as well as an index.html linking to each page's html). However, we want a single html file that contains each individual 'page' html's content in a div, and need to do some further HTML style, attribute and structure modifications to massage the xpdftool output to what we want for GS. In order to parse and manipulate the HTML 'DOM' to do this, we're using the Mojo::DOM package that Dr Bainbridge found and which he's compiled up. Mojo::DOM is therefore also committed in this revision. Some further changes and some display fixes are required, but need to check with the others about that.

File size: 26.3 KB
Line 
1
2=encoding utf8
3
4=head1 NAME
5
6Mojolicious::Guides::Tutorial - Get started with Mojolicious
7
8=head1 TUTORIAL
9
10A quick example-driven introduction to the wonders of L<Mojolicious::Lite>.
11Almost everything you'll learn here also applies to full L<Mojolicious>
12applications.
13
14This is only the first of the L<Mojolicious::Guides>. Other guides delve deeper
15into topics like L<growing|Mojolicious::Guides::Growing> a L<Mojolicious::Lite>
16prototype into a well-structured L<Mojolicious> application,
17L<routing|Mojolicious::Guides::Routing>,
18L<rendering|Mojolicious::Guides::Rendering> and more. It is highly encouraged
19that readers continue on to the remaining guides after reading this one.
20
21=head2 Hello World
22
23A simple Hello World application can look like this, L<strict>, L<warnings>,
24L<utf8> and Perl 5.10 L<features|feature> are automatically enabled and a few
25L<functions|Mojolicious::Lite/"FUNCTIONS"> imported, when you use
26L<Mojolicious::Lite>, turning your script into a full featured web application.
27
28 #!/usr/bin/env perl
29 use Mojolicious::Lite;
30
31 get '/' => sub {
32 my $c = shift;
33 $c->render(text => 'Hello World!');
34 };
35
36 app->start;
37
38With L<Mojolicious::Command::generate::lite_app> there is also a helper command
39to generate a small example application.
40
41 $ mojo generate lite_app myapp.pl
42
43=head2 Commands
44
45Many different L<commands|Mojolicious::Commands/"COMMANDS"> are automatically
46available from the command line. CGI and L<PSGI> environments can even be
47detected and will usually just work without commands.
48
49 $ ./myapp.pl daemon
50 Server available at http://127.0.0.1:3000
51
52 $ ./myapp.pl daemon -l http://*:8080
53 Server available at http://127.0.0.1:8080
54
55 $ ./myapp.pl cgi
56 ...CGI output...
57
58 $ ./myapp.pl get /
59 Hello World!
60
61 $ ./myapp.pl
62 ...List of available commands (or automatically detected environment)...
63
64A call to L<Mojolicious/"start"> (C<app-E<gt>start>), which starts the command
65system, should be the last expression in your application, because its return
66value can be significant.
67
68 # Use @ARGV to pick a command
69 app->start;
70
71 # Start the "daemon" command
72 app->start('daemon', '-l', 'http://*:8080');
73
74=head2 Reloading
75
76Your application will automatically reload itself if you start it with the
77L<morbo> development web server, so you don't have to restart the server after
78every change.
79
80 $ morbo ./myapp.pl
81 Server available at http://127.0.0.1:3000
82
83For more information about how to deploy your application see also
84L<Mojolicious::Guides::Cookbook/"DEPLOYMENT">.
85
86=head2 Routes
87
88Routes are basically just fancy paths that can contain different kinds of
89placeholders and usually lead to an action, if they match the path part of the
90request URL. The first argument passed to all actions (C<$c>) is a
91L<Mojolicious::Controller> object, containing both the HTTP request and
92response.
93
94 use Mojolicious::Lite;
95
96 # Route leading to an action that renders some text
97 get '/foo' => sub {
98 my $c = shift;
99 $c->render(text => 'Hello World!');
100 };
101
102 app->start;
103
104Response content is often generated by actions with
105L<Mojolicious::Controller/"render">, but more about that later.
106
107=head2 GET/POST parameters
108
109All C<GET> and C<POST> parameters sent with the request are accessible via
110L<Mojolicious::Controller/"param">.
111
112 use Mojolicious::Lite;
113
114 # /foo?user=sri
115 get '/foo' => sub {
116 my $c = shift;
117 my $user = $c->param('user');
118 $c->render(text => "Hello $user.");
119 };
120
121 app->start;
122
123=head2 Stash and templates
124
125The L<Mojolicious::Controller/"stash"> is used to pass data to templates, which
126can be inlined in the C<DATA> section. A few stash values like C<template>,
127C<text> and C<data> are reserved and will be used by
128L<Mojolicious::Controller/"render"> to decide how a response should be
129generated.
130
131 use Mojolicious::Lite;
132
133 # Route leading to an action that renders a template
134 get '/foo' => sub {
135 my $c = shift;
136 $c->stash(one => 23);
137 $c->render(template => 'magic', two => 24);
138 };
139
140 app->start;
141 __DATA__
142
143 @@ magic.html.ep
144 The magic numbers are <%= $one %> and <%= $two %>.
145
146For more information about templates see also
147L<Mojolicious::Guides::Rendering/"Embedded Perl">.
148
149=head2 HTTP
150
151L<Mojolicious::Controller/"req"> and L<Mojolicious::Controller/"res"> give you
152full access to all HTTP features and information.
153
154 use Mojolicious::Lite;
155
156 # Access request information
157 get '/agent' => sub {
158 my $c = shift;
159 my $host = $c->req->url->to_abs->host;
160 my $ua = $c->req->headers->user_agent;
161 $c->render(text => "Request by $ua reached $host.");
162 };
163
164 # Echo the request body and send custom header with response
165 post '/echo' => sub {
166 my $c = shift;
167 $c->res->headers->header('X-Bender' => 'Bite my shiny metal ass!');
168 $c->render(data => $c->req->body);
169 };
170
171 app->start;
172
173You can test the more advanced examples right from the command line with
174L<Mojolicious::Command::get>.
175
176 $ ./myapp.pl get -v -M POST -c 'test' /echo
177
178=head2 JSON
179
180JSON is the most commonly used data-interchange format for web services.
181L<Mojolicious> loves JSON and comes with the possibly fastest pure-Perl
182implementation L<Mojo::JSON> built right in, which is accessible through
183L<Mojo::Message/"json"> as well as the reserved stash value C<json>.
184
185 use Mojolicious::Lite;
186
187 # Modify the received JSON document and return it
188 put '/reverse' => sub {
189 my $c = shift;
190 my $hash = $c->req->json;
191 $hash->{message} = reverse $hash->{message};
192 $c->render(json => $hash);
193 };
194
195 app->start;
196
197You can send JSON documents from the command line with
198L<Mojolicious::Command::get>.
199
200 $ ./myapp.pl get -M PUT -c '{"message":"Hello Mojo!"}' /reverse
201
202=head2 Built-in C<exception> and C<not_found> pages
203
204During development you will encounter these pages whenever you make a mistake,
205they are gorgeous and contain a lot of valuable information that will aid you
206in debugging your application.
207
208 use Mojolicious::Lite;
209
210 # Not found (404)
211 get '/missing' => sub { shift->render(template => 'does_not_exist') };
212
213 # Exception (500)
214 get '/dies' => sub { die 'Intentional error' };
215
216 app->start;
217
218You can even use CSS selectors with L<Mojolicious::Command::get> to extract only
219the information you're actually interested in.
220
221 $ ./myapp.pl get /dies '#error'
222
223And don't worry about revealing too much information on these pages, they are
224only available during development, and will be replaced automatically with pages
225that don't reveal any sensitive information in a production environment.
226
227=head2 Route names
228
229All routes can have a name associated with them, this allows automatic template
230detection and backreferencing with L<Mojolicious::Controller/"url_for">, on
231which many methods and helpers like
232L<Mojolicious::Plugin::TagHelpers/"link_to"> rely.
233
234 use Mojolicious::Lite;
235
236 # Render the template "index.html.ep"
237 get '/' => sub {
238 my $c = shift;
239 $c->render;
240 } => 'index';
241
242 # Render the template "hello.html.ep"
243 get '/hello';
244
245 app->start;
246 __DATA__
247
248 @@ index.html.ep
249 <%= link_to Hello => 'hello' %>.
250 <%= link_to Reload => 'index' %>.
251
252 @@ hello.html.ep
253 Hello World!
254
255Nameless routes get an automatically generated one assigned that is simply
256equal to the route itself without non-word characters.
257
258=head2 Layouts
259
260Templates can have layouts too, you just select one with the helper
261L<Mojolicious::Plugin::DefaultHelpers/"layout"> and place the result of the
262current template with the helper
263L<Mojolicious::Plugin::DefaultHelpers/"content">.
264
265 use Mojolicious::Lite;
266
267 get '/with_layout';
268
269 app->start;
270 __DATA__
271
272 @@ with_layout.html.ep
273 % title 'Green';
274 % layout 'green';
275 Hello World!
276
277 @@ layouts/green.html.ep
278 <!DOCTYPE html>
279 <html>
280 <head><title><%= title %></title></head>
281 <body><%= content %></body>
282 </html>
283
284The stash or helpers like L<Mojolicious::Plugin::DefaultHelpers/"title"> can be
285used to pass additional data to the layout.
286
287=head2 Blocks
288
289Template blocks can be used like normal Perl functions and are always delimited
290by the C<begin> and C<end> keywords, they are the foundation for many helpers.
291
292 use Mojolicious::Lite;
293
294 get '/with_block' => 'block';
295
296 app->start;
297 __DATA__
298
299 @@ block.html.ep
300 % my $link = begin
301 % my ($url, $name) = @_;
302 Try <%= link_to $url => begin %><%= $name %><% end %>.
303 % end
304 <!DOCTYPE html>
305 <html>
306 <head><title>Sebastians frameworks</title></head>
307 <body>
308 %= $link->('http://mojolicious.org', 'Mojolicious')
309 %= $link->('http://catalystframework.org', 'Catalyst')
310 </body>
311 </html>
312
313=head2 Helpers
314
315Helpers are little functions you can create with the keyword
316L<Mojolicious::Lite/"helper"> and reuse throughout your whole application, from
317actions to templates.
318
319 use Mojolicious::Lite;
320
321 # A helper to identify visitors
322 helper whois => sub {
323 my $c = shift;
324 my $agent = $c->req->headers->user_agent || 'Anonymous';
325 my $ip = $c->tx->remote_address;
326 return "$agent ($ip)";
327 };
328
329 # Use helper in action and template
330 get '/secret' => sub {
331 my $c = shift;
332 my $user = $c->whois;
333 $c->app->log->debug("Request from $user");
334 };
335
336 app->start;
337 __DATA__
338
339 @@ secret.html.ep
340 We know who you are <%= whois %>.
341
342A list of all built-in ones can be found in
343L<Mojolicious::Plugin::DefaultHelpers> and L<Mojolicious::Plugin::TagHelpers>.
344
345=head2 Placeholders
346
347Route placeholders allow capturing parts of a request path until a C</> or C<.>
348separator occurs, similar to the regular expression C<([^/.]+)>. Results are
349accessible via L<Mojolicious::Controller/"stash"> and
350L<Mojolicious::Controller/"param">.
351
352 use Mojolicious::Lite;
353
354 # /foo/test
355 # /foo/test123
356 get '/foo/:bar' => sub {
357 my $c = shift;
358 my $bar = $c->stash('bar');
359 $c->render(text => "Our :bar placeholder matched $bar");
360 };
361
362 # /testsomething/foo
363 # /test123something/foo
364 get '/<:bar>something/foo' => sub {
365 my $c = shift;
366 my $bar = $c->param('bar');
367 $c->render(text => "Our :bar placeholder matched $bar");
368 };
369
370 app->start;
371
372To separate them from the surrounding text, you can surround your placeholders
373with C<E<lt>> and C<E<gt>>, which also makes the colon prefix optional.
374
375=head2 Relaxed Placeholders
376
377Relaxed placeholders allow matching of everything until a C</> occurs, similar
378to the regular expression C<([^/]+)>.
379
380 use Mojolicious::Lite;
381
382 # /hello/test
383 # /hello/test.html
384 get '/hello/#you' => 'groovy';
385
386 app->start;
387 __DATA__
388
389 @@ groovy.html.ep
390 Your name is <%= $you %>.
391
392=head2 Wildcard placeholders
393
394Wildcard placeholders allow matching absolutely everything, including C</> and
395C<.>, similar to the regular expression C<(.+)>.
396
397 use Mojolicious::Lite;
398
399 # /hello/test
400 # /hello/test123
401 # /hello/test.123/test/123
402 get '/hello/*you' => 'groovy';
403
404 app->start;
405 __DATA__
406
407 @@ groovy.html.ep
408 Your name is <%= $you %>.
409
410=head2 HTTP methods
411
412Routes can be restricted to specific request methods with different keywords
413like L<Mojolicious::Lite/"get"> and L<Mojolicious::Lite/"any">.
414
415 use Mojolicious::Lite;
416
417 # GET /hello
418 get '/hello' => sub {
419 my $c = shift;
420 $c->render(text => 'Hello World!');
421 };
422
423 # PUT /hello
424 put '/hello' => sub {
425 my $c = shift;
426 my $size = length $c->req->body;
427 $c->render(text => "You uploaded $size bytes to /hello.");
428 };
429
430 # GET|POST|PATCH /bye
431 any ['GET', 'POST', 'PATCH'] => '/bye' => sub {
432 my $c = shift;
433 $c->render(text => 'Bye World!');
434 };
435
436 # * /whatever
437 any '/whatever' => sub {
438 my $c = shift;
439 my $method = $c->req->method;
440 $c->render(text => "You called /whatever with $method.");
441 };
442
443 app->start;
444
445=head2 Optional placeholders
446
447All placeholders require a value, but by assigning them default values you can
448make capturing optional.
449
450 use Mojolicious::Lite;
451
452 # /hello
453 # /hello/Sara
454 get '/hello/:name' => {name => 'Sebastian', day => 'Monday'} => sub {
455 my $c = shift;
456 $c->render(template => 'groovy', format => 'txt');
457 };
458
459 app->start;
460 __DATA__
461
462 @@ groovy.txt.ep
463 My name is <%= $name %> and it is <%= $day %>.
464
465Default values that don't belong to a placeholder simply get merged into the
466stash all the time.
467
468=head2 Restrictive placeholders
469
470A very easy way to make placeholders more restrictive are alternatives, you just
471make a list of possible values.
472
473 use Mojolicious::Lite;
474
475 # /test
476 # /123
477 any '/:foo' => [foo => ['test', '123']] => sub {
478 my $c = shift;
479 my $foo = $c->param('foo');
480 $c->render(text => "Our :foo placeholder matched $foo");
481 };
482
483 app->start;
484
485All placeholders get compiled to a regular expression internally, this process
486can also be customized. Just make sure not to use C<^> and C<$>, or capturing
487groups C<(...)>, non-capturing groups C<(?:...)> are fine though.
488
489 use Mojolicious::Lite;
490
491 # /1
492 # /123
493 any '/:bar' => [bar => qr/\d+/] => sub {
494 my $c = shift;
495 my $bar = $c->param('bar');
496 $c->render(text => "Our :bar placeholder matched $bar");
497 };
498
499 app->start;
500
501You can take a closer look at all the generated regular expressions with the
502command L<Mojolicious::Command::routes>.
503
504 $ ./myapp.pl routes -v
505
506=head2 Under
507
508Authentication and code shared between multiple routes can be realized easily
509with routes generated by L<Mojolicious::Lite/"under">. All following routes are
510only evaluated if the callback returned a true value.
511
512 use Mojolicious::Lite;
513
514 # Authenticate based on name parameter
515 under sub {
516 my $c = shift;
517
518 # Authenticated
519 my $name = $c->param('name') || '';
520 return 1 if $name eq 'Bender';
521
522 # Not authenticated
523 $c->render(template => 'denied');
524 return undef;
525 };
526
527 # Only reached when authenticated
528 get '/' => 'index';
529
530 app->start;
531 __DATA__
532
533 @@ denied.html.ep
534 You are not Bender, permission denied.
535
536 @@ index.html.ep
537 Hi Bender.
538
539Prefixing multiple routes is another good use for it.
540
541 use Mojolicious::Lite;
542
543 # /foo
544 under '/foo';
545
546 # /foo/bar
547 get '/bar' => {text => 'foo bar'};
548
549 # /foo/baz
550 get '/baz' => {text => 'foo baz'};
551
552 # / (reset)
553 under '/' => {msg => 'whatever'};
554
555 # /bar
556 get '/bar' => {inline => '<%= $msg %> works'};
557
558 app->start;
559
560You can also group related routes with L<Mojolicious::Lite/"group">, which
561allows nesting of routes generated with L<Mojolicious::Lite/"under">.
562
563 use Mojolicious::Lite;
564
565 # Global logic shared by all routes
566 under sub {
567 my $c = shift;
568 return 1 if $c->req->headers->header('X-Bender');
569 $c->render(text => "You're not Bender.");
570 return undef;
571 };
572
573 # Admin section
574 group {
575
576 # Local logic shared only by routes in this group
577 under '/admin' => sub {
578 my $c = shift;
579 return 1 if $c->req->headers->header('X-Awesome');
580 $c->render(text => "You're not awesome enough.");
581 return undef;
582 };
583
584 # GET /admin/dashboard
585 get '/dashboard' => {text => 'Nothing to see here yet.'};
586 };
587
588 # GET /welcome
589 get '/welcome' => {text => 'Hi Bender.'};
590
591 app->start;
592
593=head2 Formats
594
595Formats can be automatically detected from file extensions like C<.html>, they
596are used to find the right template and generate the correct C<Content-Type>
597header.
598
599 use Mojolicious::Lite;
600
601 # /detection
602 # /detection.html
603 # /detection.txt
604 get '/detection' => sub {
605 my $c = shift;
606 $c->render(template => 'detected');
607 };
608
609 app->start;
610 __DATA__
611
612 @@ detected.html.ep
613 <!DOCTYPE html>
614 <html>
615 <head><title>Detected</title></head>
616 <body>HTML was detected.</body>
617 </html>
618
619 @@ detected.txt.ep
620 TXT was detected.
621
622The default format is C<html>, and restrictive placeholders can be used to
623limit possible values.
624
625 use Mojolicious::Lite;
626
627 # /hello.json
628 # /hello.txt
629 get '/hello' => [format => ['json', 'txt']] => sub {
630 my $c = shift;
631 return $c->render(json => {hello => 'world'})
632 if $c->stash('format') eq 'json';
633 $c->render(text => 'hello world');
634 };
635
636 app->start;
637
638Or you can just disable format detection with a special type of restrictive
639placeholder.
640
641 use Mojolicious::Lite;
642
643 # /hello
644 get '/hello' => [format => 0] => {text => 'No format detection.'};
645
646 # Disable detection and allow the following routes to re-enable it on demand
647 under [format => 0];
648
649 # /foo
650 get '/foo' => {text => 'No format detection again.'};
651
652 # /bar.txt
653 get '/bar' => [format => 'txt'] => {text => ' Just one format.'};
654
655 app->start;
656
657=head2 Content negotiation
658
659For resources with different representations and that require truly RESTful
660content negotiation you can also use L<Mojolicious::Controller/"respond_to">.
661
662 use Mojolicious::Lite;
663
664 # /hello (Accept: application/json)
665 # /hello (Accept: application/xml)
666 # /hello.json
667 # /hello.xml
668 # /hello?format=json
669 # /hello?format=xml
670 get '/hello' => sub {
671 my $c = shift;
672 $c->respond_to(
673 json => {json => {hello => 'world'}},
674 xml => {text => '<hello>world</hello>'},
675 any => {data => '', status => 204}
676 );
677 };
678
679 app->start;
680
681MIME type mappings can be extended or changed easily with
682L<Mojolicious/"types">.
683
684 app->types->type(rdf => 'application/rdf+xml');
685
686=head2 Static files
687
688Similar to templates, but with only a single file extension and optional Base64
689encoding, static files can be inlined in the C<DATA> section and are served
690automatically.
691
692 use Mojolicious::Lite;
693
694 app->start;
695 __DATA__
696
697 @@ something.js
698 alert('hello!');
699
700 @@ test.txt (base64)
701 dGVzdCAxMjMKbGFsYWxh
702
703External static files are not limited to a single file extension and will be
704served automatically from a C<public> directory if it exists.
705
706 $ mkdir public
707 $ mv something.js public/something.js
708 $ mv mojolicious.tar.gz public/mojolicious.tar.gz
709
710Both have a higher precedence than routes for C<GET> and C<HEAD> requests.
711Content negotiation with C<Range>, C<If-None-Match> and C<If-Modified-Since>
712headers is supported as well and can be tested very easily with
713L<Mojolicious::Command::get>.
714
715 $ ./myapp.pl get /something.js -v -H 'Range: bytes=2-4'
716
717=head2 External templates
718
719External templates will be searched by the renderer in a C<templates> directory
720if it exists.
721
722 $ mkdir -p templates/foo
723 $ echo 'Hello World!' > templates/foo/bar.html.ep
724
725They have a higher precedence than templates in the C<DATA> section.
726
727 use Mojolicious::Lite;
728
729 # Render template "templates/foo/bar.html.ep"
730 any '/external' => sub {
731 my $c = shift;
732 $c->render(template => 'foo/bar');
733 };
734
735 app->start;
736
737=head2 Home
738
739You can use L<Mojolicious/"home"> to interact with the directory your
740application considers its home. This is the directory it will search for
741C<public> and C<templates> directories, but you can use it to store all sorts of
742application specific data.
743
744 $ mkdir cache
745 $ echo 'Hello World!' > cache/hello.txt
746
747There are many useful methods L<Mojo::Home> inherits from L<Mojo::File>, like
748L<Mojo::File/"child"> and L<Mojo::File/"slurp">, that will help you keep your
749application portable across many different operating systems.
750
751 use Mojolicious::Lite;
752
753 # Load message into memory
754 my $hello = app->home->child('cache', 'hello.txt')->slurp;
755
756 # Display message
757 get '/' => sub {
758 my $c = shift;
759 $c->render(text => $hello);
760 };
761
762You can also introspect your application from the command line with
763L<Mojolicious::Command::eval>.
764
765 $ ./myapp.pl eval -v 'app->home'
766
767=head2 Conditions
768
769Conditions such as C<agent> and C<host> from
770L<Mojolicious::Plugin::HeaderCondition> allow even more powerful route
771constructs.
772
773 use Mojolicious::Lite;
774
775 # Firefox
776 get '/foo' => (agent => qr/Firefox/) => sub {
777 my $c = shift;
778 $c->render(text => 'Congratulations, you are using a cool browser.');
779 };
780
781 # Internet Explorer
782 get '/foo' => (agent => qr/Internet Explorer/) => sub {
783 my $c = shift;
784 $c->render(text => 'Dude, you really need to upgrade to Firefox.');
785 };
786
787 # http://mojolicious.org/bar
788 get '/bar' => (host => 'mojolicious.org') => sub {
789 my $c = shift;
790 $c->render(text => 'Hello Mojolicious.');
791 };
792
793 app->start;
794
795=head2 Sessions
796
797Cookie-based sessions just work out of the box, as soon as you start using them
798through the helper L<Mojolicious::Plugin::DefaultHelpers/"session">. Just be
799aware that all session data gets serialized with L<Mojo::JSON> and stored
800client-side, with a cryptographic signature to prevent tampering.
801
802 use Mojolicious::Lite;
803
804 # Access session data in action and template
805 get '/counter' => sub {
806 my $c = shift;
807 $c->session->{counter}++;
808 };
809
810 app->start;
811 __DATA__
812
813 @@ counter.html.ep
814 Counter: <%= session 'counter' %>
815
816Note that you should use custom L<Mojolicious/"secrets"> to make signed cookies
817really tamper resistant.
818
819 app->secrets(['My secret passphrase here']);
820
821=head2 File uploads
822
823All files uploaded via C<multipart/form-data> request are automatically
824available as L<Mojo::Upload> objects from L<Mojolicious::Controller/"param">.
825And you don't have to worry about memory usage, because all files above 250KiB
826will be automatically streamed into a temporary file. To build HTML forms more
827efficiently, you can also use tag helpers like
828L<Mojolicious::Plugin::TagHelpers/"form_for">.
829
830 use Mojolicious::Lite;
831
832 # Upload form in DATA section
833 get '/' => 'form';
834
835 # Multipart upload handler
836 post '/upload' => sub {
837 my $c = shift;
838
839 # Check file size
840 return $c->render(text => 'File is too big.', status => 200)
841 if $c->req->is_limit_exceeded;
842
843 # Process uploaded file
844 return $c->redirect_to('form') unless my $example = $c->param('example');
845 my $size = $example->size;
846 my $name = $example->filename;
847 $c->render(text => "Thanks for uploading $size byte file $name.");
848 };
849
850 app->start;
851 __DATA__
852
853 @@ form.html.ep
854 <!DOCTYPE html>
855 <html>
856 <head><title>Upload</title></head>
857 <body>
858 %= form_for upload => (enctype => 'multipart/form-data') => begin
859 %= file_field 'example'
860 %= submit_button 'Upload'
861 % end
862 </body>
863 </html>
864
865To protect you from excessively large files there is also a limit of 16MiB by
866default, which you can tweak with the attribute
867L<Mojolicious/"max_request_size">.
868
869 # Increase limit to 1GiB
870 app->max_request_size(1073741824);
871
872=head2 User agent
873
874With L<Mojo::UserAgent>, which is available through the helper
875L<Mojolicious::Plugin::DefaultHelpers/"ua">, there's a full featured HTTP and
876WebSocket user agent built right in. Especially in combination with
877L<Mojo::JSON> and L<Mojo::DOM> this can be a very powerful tool.
878
879 use Mojolicious::Lite;
880
881 # Blocking
882 get '/headers' => sub {
883 my $c = shift;
884 my $url = $c->param('url') || 'https://mojolicious.org';
885 my $dom = $c->ua->get($url)->result->dom;
886 $c->render(json => $dom->find('h1, h2, h3')->map('text')->to_array);
887 };
888
889 # Non-blocking
890 get '/title' => sub {
891 my $c = shift;
892 $c->ua->get('mojolicious.org' => sub {
893 my ($ua, $tx) = @_;
894 $c->render(data => $tx->result->dom->at('title')->text);
895 });
896 };
897
898 # Concurrent non-blocking
899 get '/titles' => sub {
900 my $c = shift;
901 my $mojo = $c->ua->get_p('https://mojolicious.org');
902 my $cpan = $c->ua->get_p('https://metacpan.org');
903 Mojo::Promise->all($mojo, $cpan)->then(sub {
904 my ($mojo, $cpan) = @_;
905 $c->render(json => {
906 mojo => $mojo->[0]->result->dom->at('title')->text,
907 cpan => $cpan->[0]->result->dom->at('title')->text
908 });
909 })->wait;
910 };
911
912 app->start;
913
914For more information about the user agent see also
915L<Mojolicious::Guides::Cookbook/"USER AGENT">.
916
917=head2 WebSockets
918
919WebSocket applications have never been this simple before. Just receive
920messages by subscribing to events such as
921L<Mojo::Transaction::WebSocket/"json"> with L<Mojolicious::Controller/"on"> and
922return them with L<Mojolicious::Controller/"send">.
923
924 use Mojolicious::Lite;
925
926 websocket '/echo' => sub {
927 my $c = shift;
928 $c->on(json => sub {
929 my ($c, $hash) = @_;
930 $hash->{msg} = "echo: $hash->{msg}";
931 $c->send({json => $hash});
932 });
933 };
934
935 get '/' => 'index';
936
937 app->start;
938 __DATA__
939
940 @@ index.html.ep
941 <!DOCTYPE html>
942 <html>
943 <head>
944 <title>Echo</title>
945 <script>
946 var ws = new WebSocket('<%= url_for('echo')->to_abs %>');
947 ws.onmessage = function (event) {
948 document.body.innerHTML += JSON.parse(event.data).msg;
949 };
950 ws.onopen = function (event) {
951 ws.send(JSON.stringify({msg: 'I ♥ Mojolicious!'}));
952 };
953 </script>
954 </head>
955 </html>
956
957For more information about real-time web features see also
958L<Mojolicious::Guides::Cookbook/"REAL-TIME WEB">.
959
960=head2 Mode
961
962You can use the L<Mojo::Log> object from L<Mojolicious/"log"> to portably
963collect debug messages and automatically disable them later in a production
964setup by changing the L<Mojolicious> operating mode, which can also be retrieved
965from the attribute L<Mojolicious/"mode">.
966
967 use Mojolicious::Lite;
968
969 # Prepare mode specific message during startup
970 my $msg = app->mode eq 'development' ? 'Development!' : 'Something else!';
971
972 get '/' => sub {
973 my $c = shift;
974 $c->app->log->debug('Rendering mode specific message');
975 $c->render(text => $msg);
976 };
977
978 app->log->debug('Starting application');
979 app->start;
980
981The default operating mode will usually be C<development> and can be changed
982with command line options or the C<MOJO_MODE> and C<PLACK_ENV> environment
983variables. A mode other than C<development> will raise the log level from
984C<debug> to C<info>.
985
986 $ ./myapp.pl daemon -m production
987
988All messages will be written to C<STDERR> or a C<log/$mode.log> file if a
989C<log> directory exists.
990
991 $ mkdir log
992
993Mode changes also affect a few other aspects of the framework, such as the
994built-in C<exception> and C<not_found> pages. Once you switch modes from
995C<development> to C<production>, no sensitive information will be revealed on
996those pages anymore.
997
998=head2 Testing
999
1000Testing your application is as easy as creating a C<t> directory and filling it
1001with normal Perl tests like C<t/basic.t>, which can be a lot of fun thanks to
1002L<Test::Mojo>.
1003
1004 use Test::More;
1005 use Test::Mojo;
1006
1007 use FindBin;
1008 require "$FindBin::Bin/../myapp.pl";
1009
1010 my $t = Test::Mojo->new;
1011 $t->get_ok('/')->status_is(200)->content_like(qr/Funky/);
1012
1013 done_testing();
1014
1015Just run your tests with the command L<Mojolicious::Command::test> or L<prove>.
1016
1017 $ ./myapp.pl test
1018 $ ./myapp.pl test -v t/basic.t
1019 $ prove -l -v t/basic.t
1020
1021=head1 MORE
1022
1023You can continue with L<Mojolicious::Guides> now or take a look at the
1024L<Mojolicious wiki|http://github.com/kraih/mojo/wiki>, which contains a lot more
1025documentation and examples by many different authors.
1026
1027=head1 SUPPORT
1028
1029If you have any questions the documentation might not yet answer, don't
1030hesitate to ask on the
1031L<mailing list|http://groups.google.com/group/mojolicious> or the official IRC
1032channel C<#mojo> on C<irc.perl.org>
1033(L<chat now!|https://chat.mibbit.com/?channel=%23mojo&server=irc.perl.org>).
1034
1035=cut
Note: See TracBrowser for help on using the repository browser.