1Mojolicious::Guides::TuUtsoerriaClo(n3t)ributed Perl DocMuomjeonltiactiioouns::Guides::Tutorial(3)
2
3
4

NAME

6       Mojolicious::Guides::Tutorial - Get started with Mojolicious
7

TUTORIAL

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

MORE

983       You can continue with Mojolicious::Guides now or take a look at the
984       Mojolicious wiki <https://github.com/mojolicious/mojo/wiki>, which
985       contains a lot more documentation and examples by many different
986       authors.
987

SUPPORT

989       If you have any questions the documentation might not yet answer, don't
990       hesitate to ask in the Forum <https://forum.mojolicious.org> or the
991       official IRC channel "#mojo" on "chat.freenode.net" (chat now!
992       <https://webchat.freenode.net/#mojo>).
993
994
995
996perl v5.32.1                      2021-02-07  Mojolicious::Guides::Tutorial(3)
Impressum