1Mojolicious::Guides::ReUnsdeerriCnogn(t3r)ibuted Perl DoMcoujmoelnitcaitoiuosn::Guides::Rendering(3)
2
3
4
6 Mojolicious::Guides::Rendering - Rendering content
7
9 This document explains content generation with the Mojolicious
10 renderer.
11
13 Essentials every Mojolicious developer should know.
14
15 Renderer
16 The renderer is a tiny black box turning stash data into actual
17 responses utilizing multiple template systems and data encoding
18 modules.
19
20 {text => 'Hello.'} -> 200 OK, text/html, 'Hello.'
21 {json => {x => 3}} -> 200 OK, application/json, '{"x":3}'
22 {text => 'Oops.', status => '410'} -> 410 Gone, text/html, 'Oops.'
23
24 Templates can be automatically detected if enough information is
25 provided by the developer or routes. Template names are expected to
26 follow the "template.format.handler" scheme, with "template" defaulting
27 to "controller/action" or the route name, "format" defaulting to "html"
28 and "handler" to "ep".
29
30 {controller => 'users', action => 'list'} -> 'users/list.html.ep'
31 {template => 'foo', format => 'txt'} -> 'foo.txt.ep'
32 {template => 'foo', handler => 'epl'} -> 'foo.html.epl'
33
34 The "controller" value gets converted from "CamelCase" to "snake_case"
35 using "decamelize" in Mojo::Util and "-" characters replaced with "/".
36
37 {controller => 'My::Users', action => 'add'} -> 'my/users/add.html.ep'
38 {controller => 'my-users', action => 'show'} -> 'my/users/show.html.ep'
39
40 All templates should be in the "templates" directories of the
41 application, which can be customized with "paths" in
42 Mojolicious::Renderer, or one of the the "DATA" sections from "classes"
43 in Mojolicious::Renderer.
44
45 __DATA__
46
47 @@ time.html.ep
48 % use Time::Piece;
49 % my $now = localtime;
50 <!DOCTYPE html>
51 <html>
52 <head><title>Time</title></head>
53 <body>The time is <%= $now->hms %>.</body>
54 </html>
55
56 @@ hello.txt.ep
57 ...
58
59 The renderer can be easily extended to support additional template
60 systems with plugins, but more about that later.
61
62 Embedded Perl
63 Mojolicious includes a minimalistic but very powerful template system
64 out of the box called Embedded Perl or "ep" for short. It is based on
65 Mojo::Template and allows the embedding of Perl code right into actual
66 content using a small set of special tags and line start characters.
67 For all templates strict, warnings, utf8 and Perl 5.16 features are
68 automatically enabled.
69
70 <% Perl code %>
71 <%= Perl expression, replaced with XML escaped result %>
72 <%== Perl expression, replaced with result %>
73 <%# Comment, useful for debugging %>
74 <%% Replaced with "<%", useful for generating templates %>
75 % Perl code line, treated as "<% line =%>" (explained later)
76 %= Perl expression line, treated as "<%= line %>"
77 %== Perl expression line, treated as "<%== line %>"
78 %# Comment line, useful for debugging
79 %% Replaced with "%", useful for generating templates
80
81 Tags and lines work pretty much the same, but depending on context one
82 will usually look a bit better. Semicolons get automatically appended
83 to all expressions.
84
85 <% my $i = 10; %>
86 <ul>
87 <% for my $j (1 .. $i) { %>
88 <li>
89 <%= $j %>
90 </li>
91 <% } %>
92 </ul>
93
94 % my $i = 10;
95 <ul>
96 % for my $j (1 .. $i) {
97 <li>
98 %= $j
99 </li>
100 % }
101 </ul>
102
103 Aside from differences in whitespace handling, both examples generate
104 similar Perl code, a naive translation could look like this.
105
106 my $output = '';
107 my $i = 10;
108 $output .= '<ul>';
109 for my $j (1 .. $i) {
110 $output .= '<li>';
111 $output .= xml_escape scalar + $j;
112 $output .= '</li>';
113 }
114 $output .= '</ul>';
115 return $output;
116
117 An additional equal sign can be used to disable escaping of the
118 characters "<", ">", "&", "'" and """ in results from Perl expressions,
119 which is the default to prevent XSS attacks against your application.
120
121 <%= 'I ♥ Mojolicious!' %>
122 <%== '<p>I ♥ Mojolicious!</p>' %>
123
124 Only Mojo::ByteStream objects are excluded from automatic escaping.
125
126 <%= b('<p>I ♥ Mojolicious!</p>') %>
127
128 Whitespace characters around tags can be trimmed by adding an
129 additional equal sign to the end of a tag.
130
131 <% for (1 .. 3) { %>
132 <%= 'Trim all whitespace characters around this expression' =%>
133 <% } %>
134
135 Newline characters can be escaped with a backslash.
136
137 This is <%= 1 + 1 %> a\
138 single line
139
140 And a backslash in front of a newline character can be escaped with
141 another backslash.
142
143 This will <%= 1 + 1 %> result\\
144 in multiple\\
145 lines
146
147 A newline character gets appended automatically to every template,
148 unless the last character is a backslash. And empty lines at the end of
149 a template are ignored.
150
151 There is <%= 1 + 1 %> no newline at the end here\
152
153 At the beginning of the template, stash values that don't have invalid
154 characters in their name get automatically initialized as normal
155 variables, and the controller object as both $self and $c.
156
157 $c->stash(name => 'tester');
158
159 Hello <%= $name %> from <%= $c->tx->remote_address %>.
160
161 A prefix like "myapp.*" is commonly used for stash values that you
162 don't want to expose in templates.
163
164 $c->stash('myapp.name' => 'tester');
165
166 There are also many helper functions available, but more about that
167 later.
168
169 <%= dumper {foo => 'bar'} %>
170
172 Most commonly used features every Mojolicious developer should know
173 about.
174
175 Automatic rendering
176 The renderer can be manually started by calling the method "render" in
177 Mojolicious::Controller, but that's usually not necessary, because it
178 will get automatically called if nothing has been rendered after the
179 router finished its work. This also means you can have routes pointing
180 only to templates without actual actions.
181
182 $c->render;
183
184 There is one big difference though, by calling it manually you can make
185 sure that templates use the current controller object, and not the
186 default controller specified with the attribute "controller_class" in
187 Mojolicious.
188
189 $c->render_later;
190
191 You can also disable automatic rendering with the method "render_later"
192 in Mojolicious::Controller, which can be very useful to delay rendering
193 when a non-blocking operation has to be performed first.
194
195 Rendering templates
196 The renderer will always try to detect the right template, but you can
197 also use the "template" stash value to render a specific one.
198 Everything before the last slash will be interpreted as the
199 subdirectory path in which to find the template.
200
201 # foo/bar/baz.*.*
202 $c->render(template => 'foo/bar/baz');
203
204 Choosing a specific "format" and "handler" is just as easy.
205
206 # foo/bar/baz.txt.epl
207 $c->render(template => 'foo/bar/baz', format => 'txt', handler => 'epl');
208
209 Because rendering a specific template is the most common task it also
210 has a shortcut.
211
212 $c->render('foo/bar/baz');
213
214 If you're not sure in advance if a template actually exists, you can
215 also use the method "render_maybe" in Mojolicious::Controller to try
216 multiple alternatives.
217
218 $c->render_maybe('localized/baz') or $c->render('foo/bar/baz');
219
220 Rendering to strings
221 Sometimes you might want to use the rendered result directly instead of
222 generating a response, for example, to send emails, this can be done
223 with "render_to_string" in Mojolicious::Controller.
224
225 my $html = $c->render_to_string('mail');
226
227 No encoding will be performed, making it easy to reuse the result in
228 other templates or to generate binary data.
229
230 my $pdf = $c->render_to_string('invoice', format => 'pdf');
231 $c->render(data => $pdf, format => 'pdf');
232
233 All arguments passed will get localized automatically and are only
234 available during this render operation.
235
236 Template variants
237 To make your application look great on many different devices you can
238 also use the "variant" stash value to choose between different variants
239 of your templates.
240
241 # foo/bar/baz.html+phone.ep
242 # foo/bar/baz.html.ep
243 $c->render('foo/bar/baz', variant => 'phone');
244
245 This can be done very liberally since it only applies when a template
246 with the correct name actually exists and falls back to the generic one
247 otherwise.
248
249 Rendering inline templates
250 Some renderers such as "ep" allow templates to be passed "inline".
251
252 $c->render(inline => 'The result is <%= 1 + 1 %>.');
253
254 Since auto-detection depends on a path you might have to supply a
255 "handler" too.
256
257 $c->render(inline => "<%= shift->param('foo') %>", handler => 'epl');
258
259 Rendering text
260 Characters can be rendered to bytes with the "text" stash value, the
261 given content will be automatically encoded with "encoding" in
262 Mojolicious::Renderer.
263
264 $c->render(text => 'I ♥ Mojolicious!');
265
266 Rendering data
267 Bytes can be rendered with the "data" stash value, no encoding will be
268 performed.
269
270 $c->render(data => $bytes);
271
272 Rendering JSON
273 The "json" stash value allows you to pass Perl data structures to the
274 renderer which get directly encoded to JSON with Mojo::JSON.
275
276 $c->render(json => {foo => [1, 'test', 3]});
277
278 Status code
279 Response status codes can be changed with the "status" stash value.
280
281 $c->render(text => 'Oops.', status => 500);
282
283 Content type
284 The "Content-Type" header of the response is actually based on the MIME
285 type mapping of the "format" stash value.
286
287 # Content-Type: text/plain
288 $c->render(text => 'Hello.', format => 'txt');
289
290 # Content-Type: image/png
291 $c->render(data => $bytes, format => 'png');
292
293 These mappings can be easily extended or changed with "types" in
294 Mojolicious.
295
296 # Add new MIME type
297 $app->types->type(md => 'text/markdown');
298
299 Stash data
300 Any of the native Perl data types can be passed to templates as
301 references through the "stash" in Mojolicious::Controller.
302
303 $c->stash(description => 'web framework');
304 $c->stash(frameworks => ['Catalyst', 'Mojolicious']);
305 $c->stash(spinoffs => {minion => 'job queue'});
306
307 %= $description
308 %= $frameworks->[1]
309 %= $spinoffs->{minion}
310
311 Since everything is just Perl normal control structures just work.
312
313 % for my $framework (@$frameworks) {
314 <%= $framework %> is a <%= $description %>.
315 % }
316
317 % if (my $description = $spinoffs->{minion}) {
318 Minion is a <%= $description %>.
319 % }
320
321 For templates that might get rendered in different ways and where
322 you're not sure if a stash value will actually be set, you can just use
323 the helper "stash" in Mojolicious::Plugin::DefaultHelpers.
324
325 % if (my $spinoffs = stash 'spinoffs') {
326 Minion is a <%= $spinoffs->{minion} %>.
327 % }
328
329 Helpers
330 Helpers are little functions you can use in templates as well as
331 application and controller code.
332
333 # Template
334 %= dumper [1, 2, 3]
335
336 # Application
337 my $serialized = $app->dumper([1, 2, 3]);
338
339 # Controller
340 my $serialized = $c->dumper([1, 2, 3]);
341
342 We differentiate between default helpers, which are more general
343 purpose like "dumper" in Mojolicious::Plugin::DefaultHelpers, and tag
344 helpers like "link_to" in Mojolicious::Plugin::TagHelpers, which are
345 template specific and mostly used to generate HTML tags.
346
347 %= link_to Mojolicious => 'https://mojolicious.org'
348
349 In controllers you can also use the method "helpers" in
350 Mojolicious::Controller to fully qualify helper calls and ensure that
351 they don't conflict with existing methods you may already have.
352
353 my $serialized = $c->helpers->dumper([1, 2, 3]);
354
355 A list of all built-in helpers can be found in
356 Mojolicious::Plugin::DefaultHelpers and
357 Mojolicious::Plugin::TagHelpers.
358
359 Content negotiation
360 For resources with different representations and that require truly
361 RESTful content negotiation you can also use "respond_to" in
362 Mojolicious::Plugin::DefaultHelpers instead of "render" in
363 Mojolicious::Controller.
364
365 # /hello (Accept: application/json) -> "json"
366 # /hello (Accept: application/xml) -> "xml"
367 # /hello.json -> "json"
368 # /hello.xml -> "xml"
369 # /hello?_format=json -> "json"
370 # /hello?_format=xml -> "xml"
371 $c->respond_to(
372 json => {json => {hello => 'world'}},
373 xml => {text => '<hello>world</hello>'}
374 );
375
376 The best possible representation will be automatically selected from
377 the "_format" "GET"/"POST" parameter, "format" stash value or "Accept"
378 request header and stored in the "format" stash value. To change MIME
379 type mappings for the "Accept" request header or the "Content-Type"
380 response header you can use "types" in Mojolicious.
381
382 $c->respond_to(
383 json => {json => {hello => 'world'}},
384 html => sub {
385 $c->content_for(head => '<meta name="author" content="sri">');
386 $c->render(template => 'hello', message => 'world')
387 }
388 );
389
390 Callbacks can be used for representations that are too complex to fit
391 into a single render call.
392
393 # /hello (Accept: application/json) -> "json"
394 # /hello (Accept: text/html) -> "html"
395 # /hello (Accept: image/png) -> "any"
396 # /hello.json -> "json"
397 # /hello.html -> "html"
398 # /hello.png -> "any"
399 # /hello?_format=json -> "json"
400 # /hello?_format=html -> "html"
401 # /hello?_format=png -> "any"
402 $c->respond_to(
403 json => {json => {hello => 'world'}},
404 html => {template => 'hello', message => 'world'},
405 any => {text => '', status => 204}
406 );
407
408 And if no viable representation could be found, the "any" fallback will
409 be used or an empty 204 response rendered automatically.
410
411 # /hello -> "html"
412 # /hello (Accept: text/html) -> "html"
413 # /hello (Accept: text/xml) -> "xml"
414 # /hello (Accept: text/plain) -> undef
415 # /hello.html -> "html"
416 # /hello.xml -> "xml"
417 # /hello.txt -> undef
418 # /hello?_format=html -> "html"
419 # /hello?_format=xml -> "xml"
420 # /hello?_format=txt -> undef
421 if (my $format = $c->accepts('html', 'xml')) {
422 ...
423 }
424
425 For even more advanced negotiation logic you can also use the helper
426 "accepts" in Mojolicious::Plugin::DefaultHelpers.
427
428 Rendering "exception" and "not_found" pages
429 By now you've probably already encountered the built-in 404 (Not Found)
430 and 500 (Server Error) pages, that get rendered automatically when you
431 make a mistake. Those are fallbacks for when your own exception
432 handling fails, which can be especially helpful during development. You
433 can also render them manually with the helpers "reply->exception" in
434 Mojolicious::Plugin::DefaultHelpers and "reply->not_found" in
435 Mojolicious::Plugin::DefaultHelpers.
436
437 use Mojolicious::Lite -signatures;
438 use Scalar::Util qw(looks_like_number);
439
440 get '/divide/:dividend/by/:divisor' => sub ($c) {
441
442 my $dividend = $c->param('dividend');
443 my $divisor = $c->param('divisor');
444
445 # 404
446 return $c->reply->not_found unless looks_like_number $dividend && looks_like_number $divisor;
447
448 # 500
449 return $c->reply->exception('Division by zero!') if $divisor == 0;
450
451 # 200
452 $c->render(text => $dividend / $divisor);
453 };
454
455 app->start;
456
457 To change the HTTP status code of the exception, you can use "rendered"
458 in Mojolicious::Controller.
459
460 return $c->reply->exception('Division by zero!')->rendered(400) if $divisor == 0;
461
462 You can also change the templates of those pages, since you most likely
463 want to show your users something more closely related to your
464 application in production. The renderer will always try to find
465 "exception.$mode.$format.*" or "not_found.$mode.$format.*" before
466 falling back to the built-in default templates.
467
468 use Mojolicious::Lite;
469
470 get '/dies' => sub { die 'Intentional error' };
471
472 app->start;
473 __DATA__
474
475 @@ exception.production.html.ep
476 <!DOCTYPE html>
477 <html>
478 <head><title>Server error</title></head>
479 <body>
480 <h1>Exception</h1>
481 <p><%= $exception->message %></p>
482 <h1>Stash</h1>
483 <pre><%= dumper $snapshot %></pre>
484 </body>
485 </html>
486
487 The hook "before_render" in Mojolicious makes even more advanced
488 customizations possible by allowing you to intercept and modify the
489 arguments passed to the renderer.
490
491 use Mojolicious::Lite -signatures;
492
493 hook before_render => sub ($c, $args) {
494
495 # Make sure we are rendering the exception template
496 return unless my $template = $args->{template};
497 return unless $template eq 'exception';
498
499 # Switch to JSON rendering if content negotiation allows it
500 return unless $c->accepts('json');
501 $args->{json} = {exception => $c->stash('exception')};
502 };
503
504 get '/' => sub { die "This sho...ALL GLORY TO THE HYPNOTOAD!\n" };
505
506 app->start;
507
508 Layouts
509 Most of the time when using "ep" templates you will want to wrap your
510 generated content in an HTML skeleton, thanks to layouts that's
511 absolutely trivial.
512
513 use Mojolicious::Lite;
514
515 get '/' => {template => 'foo/bar'};
516
517 app->start;
518 __DATA__
519
520 @@ foo/bar.html.ep
521 % layout 'mylayout';
522 Hello World!
523
524 @@ layouts/mylayout.html.ep
525 <!DOCTYPE html>
526 <html>
527 <head><title>MyApp</title></head>
528 <body><%= content %></body>
529 </html>
530
531 You just select the right layout template with the helper "layout" in
532 Mojolicious::Plugin::DefaultHelpers and place the result of the current
533 template with the helper "content" in
534 Mojolicious::Plugin::DefaultHelpers. You can also pass along normal
535 stash values to the "layout" helper.
536
537 use Mojolicious::Lite;
538
539 get '/' => {template => 'foo/bar'};
540
541 app->start;
542 __DATA__
543
544 @@ foo/bar.html.ep
545 % layout 'mylayout', title => 'Hi there';
546 Hello World!
547
548 @@ layouts/mylayout.html.ep
549 <!DOCTYPE html>
550 <html>
551 <head><title><%= $title %></title></head>
552 <body><%= content %></body>
553 </html>
554
555 Instead of the "layout" helper you could also just use the "layout"
556 stash value, or call "render" in Mojolicious::Controller with the
557 "layout" argument.
558
559 $c->render(template => 'mytemplate', layout => 'mylayout');
560
561 To set a "layout" stash value application-wide you can use "defaults"
562 in Mojolicious.
563
564 $app->defaults(layout => 'mylayout');
565
566 Layouts can also be used with "render_to_string" in
567 Mojolicious::Controller, but the "layout" value needs to be passed as a
568 render argument (not a stash value).
569
570 my $html = $c->render_to_string('reminder', layout => 'mail');
571
572 Partial templates
573 You can break up bigger templates into smaller, more manageable chunks.
574 These partial templates can also be shared with other templates. Just
575 use the helper "include" in Mojolicious::Plugin::DefaultHelpers to
576 include one template into another.
577
578 use Mojolicious::Lite;
579
580 get '/' => {template => 'foo/bar'};
581
582 app->start;
583 __DATA__
584
585 @@ foo/bar.html.ep
586 <!DOCTYPE html>
587 <html>
588 %= include '_header', title => 'Howdy'
589 <body>Bar</body>
590 </html>
591
592 @@ _header.html.ep
593 <head><title><%= $title %></title></head>
594
595 You can name partial templates however you like, but a leading
596 underscore is a commonly used naming convention.
597
598 Reusable template blocks
599 It's never fun to repeat yourself, that's why you can build reusable
600 template blocks in "ep" that work very similar to normal Perl
601 functions, with the "begin" and "end" keywords. Just be aware that both
602 keywords are part of the surrounding tag and not actual Perl code, so
603 there can only be whitespace after "begin" and before "end".
604
605 use Mojolicious::Lite;
606
607 get '/' => 'welcome';
608
609 app->start;
610 __DATA__
611
612 @@ welcome.html.ep
613 <% my $block = begin %>
614 % my $name = shift;
615 Hello <%= $name %>.
616 <% end %>
617 <%= $block->('Wolfgang') %>
618 <%= $block->('Baerbel') %>
619
620 A naive translation of the template to Perl code could look like this.
621
622 my $output = '';
623 my $block = sub ($name) {
624 my $output = '';
625 $output .= 'Hello ';
626 $output .= xml_escape scalar + $name;
627 $output .= '.';
628 return Mojo::ByteStream->new($output);
629 };
630 $output .= xml_escape scalar + $block->('Wolfgang');
631 $output .= xml_escape scalar + $block->('Baerbel');
632 return $output;
633
634 While template blocks cannot be shared between templates, they are most
635 commonly used to pass parts of a template to helpers.
636
637 Adding helpers
638 You should always try to keep your actions small and reuse as much code
639 as possible. Helpers make this very easy, they get passed the current
640 controller object as first argument, and you can use them to do pretty
641 much anything an action could do.
642
643 use Mojolicious::Lite -signatures;
644
645 helper debug => sub ($c, $str) {
646 $c->app->log->debug($str);
647 };
648
649 get '/' => sub ($c) {
650 $c->debug('Hello from an action!');
651 } => 'index';
652
653 app->start;
654 __DATA__
655
656 @@ index.html.ep
657 % debug 'Hello from a template!';
658
659 Helpers can also accept template blocks as last argument, this for
660 example, allows very pleasant to use tag helpers and filters. Wrapping
661 the helper result into a Mojo::ByteStream object can prevent accidental
662 double escaping.
663
664 use Mojolicious::Lite -signatures;
665 use Mojo::ByteStream;
666
667 helper trim_newline => sub ($c, $block) {
668 my $result = $block->();
669 $result =~ s/\n//g;
670 return Mojo::ByteStream->new($result);
671 };
672
673 get '/' => 'index';
674
675 app->start;
676 __DATA__
677
678 @@ index.html.ep
679 %= trim_newline begin
680 Some text.
681 %= 1 + 1
682 More text.
683 % end
684
685 Similar to stash values, you can use a prefix like "myapp.*" to keep
686 helpers from getting exposed in templates as functions, and to organize
687 them into namespaces as your application grows. Every prefix
688 automatically becomes a helper that returns a proxy object containing
689 the current controller object and on which you can call the nested
690 helpers.
691
692 use Mojolicious::Lite -signatures;
693
694 helper 'cache_control.no_caching' => sub ($c) { $c->res->headers->cache_control('private, max-age=0, no-cache') };
695 helper 'cache_control.five_minutes' => sub ($c) { $c->res->headers->cache_control('public, max-age=300') };
696
697 get '/news' => sub ($c) {
698 $c->cache_control->no_caching;
699 $c->render(text => 'Always up to date.');
700 };
701
702 get '/some_older_story' => sub ($c) {
703 $c->cache_control->five_minutes;
704 $c->render(text => 'This one can be cached for a bit.');
705 };
706
707 app->start;
708
709 While helpers can also be redefined, this should only be done very
710 carefully to avoid conflicts.
711
712 Content blocks
713 The helper "content_for" in Mojolicious::Plugin::DefaultHelpers allows
714 you to pass whole blocks of content from one template to another. This
715 can be very useful when your layout has distinct sections, such as
716 sidebars, where content should be inserted by the template.
717
718 use Mojolicious::Lite;
719
720 get '/' => 'foo';
721
722 app->start;
723 __DATA__
724
725 @@ foo.html.ep
726 % layout 'mylayout';
727 % content_for header => begin
728 <meta http-equiv="Content-Type" content="text/html">
729 % end
730 <div>Hello World!</div>
731 % content_for header => begin
732 <meta http-equiv="Pragma" content="no-cache">
733 % end
734
735 @@ layouts/mylayout.html.ep
736 <!DOCTYPE html>
737 <html>
738 <head><%= content 'header' %></head>
739 <body><%= content %></body>
740 </html>
741
742 Forms
743 To build HTML forms more efficiently you can use tag helpers like
744 "form_for" in Mojolicious::Plugin::TagHelpers, which can automatically
745 select a request method for you if a route name is provided. And since
746 most browsers only allow forms to be submitted with "GET" and "POST",
747 but not request methods like "PUT" or "DELETE", they are spoofed with
748 an "_method" query parameter.
749
750 use Mojolicious::Lite -signatures;
751
752 get '/' => 'form';
753
754 # PUT /nothing
755 # POST /nothing?_method=PUT
756 put '/nothing' => sub ($c) {
757
758 # Prevent double form submission with redirect
759 my $value = $c->param('whatever');
760 $c->flash(confirmation => "We did nothing with your value ($value).");
761 $c->redirect_to('form');
762 };
763
764 app->start;
765 __DATA__
766
767 @@ form.html.ep
768 <!DOCTYPE html>
769 <html>
770 <body>
771 % if (my $confirmation = flash 'confirmation') {
772 <p><%= $confirmation %></p>
773 % }
774 %= form_for nothing => begin
775 %= text_field whatever => 'I ♥ Mojolicious!'
776 %= submit_button
777 % end
778 </body>
779 </html>
780
781 The helpers "flash" in Mojolicious::Plugin::DefaultHelpers and
782 "redirect_to" in Mojolicious::Plugin::DefaultHelpers are often used
783 together to prevent double form submission, allowing users to receive a
784 confirmation message that will vanish if they decide to reload the page
785 they've been redirected to.
786
787 Form validation
788 You can use "validation" in Mojolicious::Plugin::DefaultHelpers to
789 validate "GET" and "POST" parameters submitted to your application. All
790 unknown fields will be ignored by default, so you have to decide which
791 should be required or optional before you can perform checks on their
792 values. Every check is performed right away, so you can use the results
793 immediately to build more advanced validation logic with methods like
794 "is_valid" in Mojolicious::Validator::Validation.
795
796 use Mojolicious::Lite -signatures;
797
798 get '/' => sub ($c) {
799
800 # Check if parameters have been submitted
801 my $v = $c->validation;
802 return $c->render('index') unless $v->has_data;
803
804 # Validate parameters ("pass_again" depends on "pass")
805 $v->required('user')->size(1, 20)->like(qr/^[a-z0-9]+$/);
806 $v->required('pass_again')->equal_to('pass') if $v->optional('pass')->size(7, 500)->is_valid;
807
808 # Check if validation failed
809 return $c->render('index') if $v->has_error;
810
811 # Render confirmation
812 $c->render('thanks');
813 };
814
815 app->start;
816 __DATA__
817
818 @@ index.html.ep
819 <!DOCTYPE html>
820 <html>
821 <head>
822 <style>
823 label.field-with-error { color: #dd7e5e }
824 input.field-with-error { background-color: #fd9e7e }
825 </style>
826 </head>
827 <body>
828 %= form_for index => begin
829 %= label_for user => 'Username (required, 1-20 characters, a-z/0-9)'
830 <br>
831 %= text_field 'user', id => 'user'
832 %= submit_button
833 <br>
834 %= label_for pass => 'Password (optional, 7-500 characters)'
835 <br>
836 %= password_field 'pass', id => 'pass'
837 <br>
838 %= label_for pass_again => 'Password again (equal to the value above)'
839 <br>
840 %= password_field 'pass_again', id => 'pass_again'
841 % end
842 </body>
843 </html>
844
845 @@ thanks.html.ep
846 <!DOCTYPE html>
847 <html><body>Thank you <%= validation->param('user') %>.</body></html>
848
849 Form elements generated with tag helpers from
850 Mojolicious::Plugin::TagHelpers will automatically remember their
851 previous values and add the class "field-with-error" for fields that
852 failed validation to make styling with CSS easier.
853
854 <label class="field-with-error" for="user">
855 Username (required, only characters e-t)
856 </label>
857 <input class="field-with-error" type="text" name="user" value="sri">
858
859 For a full list of available checks see also "CHECKS" in
860 Mojolicious::Validator.
861
862 Adding form validation checks
863 Validation checks can be registered with "add_check" in
864 Mojolicious::Validator and return a false value if they were
865 successful. A true value may be used to pass along additional
866 information which can then be retrieved with "error" in
867 Mojolicious::Validator::Validation.
868
869 use Mojolicious::Lite -signatures;
870
871 # Add "range" check
872 app->validator->add_check(range => sub ($v, $name, $value, $min, $max) {
873 return $value < $min || $value > $max;
874 });
875
876 get '/' => 'form';
877
878 post '/test' => sub ($c) {
879
880 # Validate parameters with custom check
881 my $v = $c->validation;
882 $v->required('number')->range(3, 23);
883
884 # Render form again if validation failed
885 return $c->render('form') if $v->has_error;
886
887 # Prevent double form submission with redirect
888 $c->flash(number => $v->param('number'));
889 $c->redirect_to('form');
890 };
891
892 app->start;
893 __DATA__
894
895 @@ form.html.ep
896 <!DOCTYPE html>
897 <html>
898 <body>
899 % if (my $number = flash 'number') {
900 <p>Thanks, the number <%= $number %> was valid.</p>
901 % }
902 %= form_for test => begin
903 % if (my $err = validation->error('number')) {
904 <p>
905 %= 'Value is required.' if $err->[0] eq 'required'
906 %= 'Value needs to be between 3 and 23.' if $err->[0] eq 'range'
907 </p>
908 % }
909 %= text_field 'number'
910 %= submit_button
911 % end
912 </body>
913 </html>
914
915 Cross-site request forgery
916 CSRF is a very common attack on web applications that trick your logged
917 in users to submit forms they did not intend to send, with something as
918 mundane as a link. All you have to do, to protect your users from this,
919 is to add an additional hidden field to your forms with "csrf_field" in
920 Mojolicious::Plugin::TagHelpers, and validate it with "csrf_protect" in
921 Mojolicious::Validator::Validation.
922
923 use Mojolicious::Lite -signatures;
924
925 get '/' => {template => 'target'};
926
927 post '/' => sub ($c) {
928
929 # Check CSRF token
930 my $v = $c->validation;
931 return $c->render(text => 'Bad CSRF token!', status => 403) if $v->csrf_protect->has_error('csrf_token');
932
933 my $city = $v->required('city')->param('city');
934 $c->render(text => "Low orbit ion cannon pointed at $city!") unless $v->has_error;
935 } => 'target';
936
937 app->start;
938 __DATA__
939
940 @@ target.html.ep
941 <!DOCTYPE html>
942 <html>
943 <body>
944 %= form_for target => begin
945 %= csrf_field
946 %= label_for city => 'Which city to point low orbit ion cannon at?'
947 %= text_field 'city', id => 'city'
948 %= submit_button
949 %= end
950 </body>
951 </html>
952
953 For Ajax requests and the like, you can also generate a token directly
954 with the helper "csrf_token" in Mojolicious::Plugin::DefaultHelpers,
955 and then pass it along with the "X-CSRF-Token" request header.
956
958 Less commonly used and more powerful features.
959
960 Template inheritance
961 Inheritance takes the layout concept above one step further, the
962 helpers "content" in Mojolicious::Plugin::DefaultHelpers and "extends"
963 in Mojolicious::Plugin::DefaultHelpers allow you to build skeleton
964 templates with named blocks that child templates can override.
965
966 use Mojolicious::Lite;
967
968 # first > mylayout
969 get '/first' => {template => 'first', layout => 'mylayout'};
970
971 # third > second > first > mylayout
972 get '/third' => {template => 'third', layout => 'mylayout'};
973
974 app->start;
975 __DATA__
976
977 @@ layouts/mylayout.html.ep
978 <!DOCTYPE html>
979 <html>
980 <head><title>Hello</title></head>
981 <body><%= content %></body>
982 </html>
983
984 @@ first.html.ep
985 %= content header => begin
986 Default header
987 % end
988 <div>Hello World!</div>
989 %= content footer => begin
990 Default footer
991 % end
992
993 @@ second.html.ep
994 % extends 'first';
995 % content header => begin
996 New header
997 % end
998
999 @@ third.html.ep
1000 % extends 'second';
1001 % content footer => begin
1002 New footer
1003 % end
1004
1005 This chain could go on and on to allow a very high level of template
1006 reuse.
1007
1008 Serving static files
1009 Static files are automatically served from the "public" directories of
1010 the application, which can be customized with "paths" in
1011 Mojolicious::Static, or one of the "DATA" sections from "classes" in
1012 Mojolicious::Static. And if that's not enough you can also serve them
1013 manually with "reply->static" in Mojolicious::Plugin::DefaultHelpers
1014 and "reply->file" in Mojolicious::Plugin::DefaultHelpers.
1015
1016 use Mojolicious::Lite -signatures;
1017
1018 get '/' => sub ($c) {
1019 $c->reply->static('index.html');
1020 };
1021
1022 get '/some_download' => sub ($c) {
1023 $c->res->headers->content_disposition('attachment; filename=bar.png;');
1024 $c->reply->static('foo/bar.png');
1025 };
1026
1027 get '/leak' => sub ($c) {
1028 $c->reply->file('/etc/passwd');
1029 };
1030
1031 app->start;
1032
1033 Custom responses
1034 Most response content, static as well as dynamic, gets served through
1035 Mojo::Asset::File and Mojo::Asset::Memory objects. For somewhat static
1036 content, like cached JSON data or temporary files, you can create your
1037 own and use the helper "reply->asset" in
1038 Mojolicious::Plugin::DefaultHelpers to serve them while allowing
1039 content negotiation to be performed with "Range", "If-Modified-Since"
1040 and "If-None-Match" headers.
1041
1042 use Mojolicious::Lite -signatures;
1043 use Mojo::Asset::File;
1044
1045 get '/leak' => sub ($c) {
1046 $c->res->headers->content_type('text/plain');
1047 $c->reply->asset(Mojo::Asset::File->new(path => '/etc/passwd'));
1048 };
1049
1050 app->start;
1051
1052 For even more control you can also just skip the helper and use
1053 "rendered" in Mojolicious::Controller to tell the renderer when you're
1054 done generating a response.
1055
1056 use Mojolicious::Lite -signatures;
1057 use Mojo::Asset::File;
1058
1059 get '/leak' => sub ($c) {
1060 $c->res->headers->content_type('text/plain');
1061 $c->res->content->asset(Mojo::Asset::File->new(path => '/etc/passwd'));
1062 $c->rendered(200);
1063 };
1064
1065 app->start;
1066
1067 Helper plugins
1068 Some helpers might be useful enough for you to share them between
1069 multiple applications, plugins make that very simple.
1070
1071 package Mojolicious::Plugin::DebugHelper;
1072 use Mojo::Base 'Mojolicious::Plugin', -signatures;
1073
1074 sub register ($self, $app, $conf) {
1075 $app->helper(debug => sub ($c, $str) {
1076 $c->app->log->debug($str);
1077 });
1078 }
1079
1080 1;
1081
1082 The "register" method will be called when you load the plugin. And to
1083 add your helper to the application, you can use "helper" in
1084 Mojolicious.
1085
1086 use Mojolicious::Lite -signatures;
1087
1088 plugin 'DebugHelper';
1089
1090 get '/' => sub ($c) {
1091 $c->debug('It works!');
1092 $c->render(text => 'Hello!');
1093 };
1094
1095 app->start;
1096
1097 A skeleton for a full CPAN compatible plugin distribution can be
1098 automatically generated.
1099
1100 $ mojo generate plugin DebugHelper
1101
1102 And if you have a "PAUSE" account (which can be requested at
1103 <http://pause.perl.org>), you are only a few commands away from
1104 releasing it to CPAN.
1105
1106 $ perl Makefile.PL
1107 $ make test
1108 $ make manifest
1109 $ make dist
1110 $ mojo cpanify -u USER -p PASS Mojolicious-Plugin-DebugHelper-0.01.tar.gz
1111
1112 Bundling assets with plugins
1113 Assets such as templates and static files can be easily bundled with
1114 your plugins, even if you plan to release them to CPAN.
1115
1116 $ mojo generate plugin AlertAssets
1117 $ mkdir Mojolicious-Plugin-AlertAssets/lib/Mojolicious/Plugin/AlertAssets
1118 $ cd Mojolicious-Plugin-AlertAssets/lib/Mojolicious/Plugin/AlertAssets
1119 $ mkdir public
1120 $ echo 'alert("Hello World!");' > public/alertassets.js
1121 $ mkdir templates
1122 $ echo '%= javascript "/alertassets.js"' > templates/alertassets.html.ep
1123
1124 Just give them reasonably unique names, ideally based on the name of
1125 your plugin, and append their respective directories to the list of
1126 search paths when "register" is called.
1127
1128 package Mojolicious::Plugin::AlertAssets;
1129 use Mojo::Base 'Mojolicious::Plugin', -signatures;
1130
1131 use Mojo::File qw(curfile);
1132
1133 sub register ($self, $app, $conf) {
1134
1135 # Append "templates" and "public" directories
1136 my $base = curfile->sibling('AlertAssets');
1137 push @{$app->renderer->paths}, $base->child('templates')->to_string;
1138 push @{$app->static->paths}, $base->child('public')->to_string;
1139 }
1140
1141 1;
1142
1143 Both will work just like normal "templates" and "public" directories
1144 once you've installed and loaded the plugin, with slightly lower
1145 precedence.
1146
1147 use Mojolicious::Lite;
1148
1149 plugin 'AlertAssets';
1150
1151 get '/alert_me';
1152
1153 app->start;
1154 __DATA__
1155
1156 @@ alert_me.html.ep
1157 <!DOCTYPE html>
1158 <html>
1159 <head>
1160 <title>Alert me!</title>
1161 %= include 'alertassets'
1162 </head>
1163 <body>You've been alerted.</body>
1164 </html>
1165
1166 And it works just the same for assets bundled in the "DATA" section of
1167 your plugin.
1168
1169 package Mojolicious::Plugin::AlertAssets;
1170 use Mojo::Base 'Mojolicious::Plugin', -signatures;
1171
1172 sub register ($self, $app, $conf) {
1173
1174 # Append class
1175 push @{$app->renderer->classes}, __PACKAGE__;
1176 push @{$app->static->classes}, __PACKAGE__;
1177 }
1178
1179 1;
1180 __DATA__
1181
1182 @@ alertassets.js
1183 alert("Hello World!");
1184
1185 @@ alertassets.html.ep
1186 %= javascript "/alertassets.js"
1187
1188 Post-processing dynamic content
1189 While post-processing tasks are generally very easy with the hook
1190 "after_dispatch" in Mojolicious, for content generated by the renderer
1191 it is a lot more efficient to use "after_render" in Mojolicious.
1192
1193 use Mojolicious::Lite -signatures;
1194 use IO::Compress::Gzip qw(gzip);
1195
1196 hook after_render => sub ($c, $output, $format) {
1197
1198 # Check if "gzip => 1" has been set in the stash
1199 return unless $c->stash->{gzip};
1200
1201 # Check if user agent accepts gzip compression
1202 return unless ($c->req->headers->accept_encoding // '') =~ /gzip/i;
1203 $c->res->headers->append(Vary => 'Accept-Encoding');
1204
1205 # Compress content with gzip
1206 $c->res->headers->content_encoding('gzip');
1207 gzip $output, \my $compressed;
1208 $$output = $compressed;
1209 };
1210
1211 get '/' => {template => 'hello', title => 'Hello', gzip => 1};
1212
1213 app->start;
1214 __DATA__
1215
1216 @@ hello.html.ep
1217 <!DOCTYPE html>
1218 <html>
1219 <head><title><%= title %></title></head>
1220 <body>Compressed content.</body>
1221 </html>
1222
1223 If you want to compress all dynamically generated content you can also
1224 activate "compress" in Mojolicious::Renderer.
1225
1226 Streaming
1227 You don't have to render all content at once, the method "write" in
1228 Mojolicious::Controller can also be used to stream a series of smaller
1229 chunks.
1230
1231 use Mojolicious::Lite -signatures;
1232
1233 get '/' => sub ($c) {
1234
1235 # Prepare body
1236 my $body = 'Hello World!';
1237 $c->res->headers->content_length(length $body);
1238
1239 # Start writing directly with a drain callback
1240 my $drain = sub ($c) {
1241 my $chunk = substr $body, 0, 1, '';
1242 $c->write($chunk, length $body ? __SUB__ : undef);
1243 };
1244 $c->$drain;
1245 };
1246
1247 app->start;
1248
1249 The drain callback will be executed whenever the entire previous chunk
1250 of data has actually been written.
1251
1252 HTTP/1.1 200 OK
1253 Date: Sat, 13 Sep 2014 16:48:29 GMT
1254 Content-Length: 12
1255 Server: Mojolicious (Perl)
1256
1257 Hello World!
1258
1259 Instead of providing a "Content-Length" header you can also call
1260 "finish" in Mojolicious::Controller and close the connection manually
1261 once you are done.
1262
1263 use Mojolicious::Lite -signatures;
1264
1265 get '/' => sub ($c) {
1266
1267 # Prepare body
1268 my $body = 'Hello World!';
1269
1270 # Start writing directly with a drain callback
1271 my $drain = sub ($c) {
1272 my $chunk = substr $body, 0, 1, '';
1273 length $chunk ? $c->write($chunk, __SUB__) : $c->finish;
1274 };
1275 $c->$drain;
1276 };
1277
1278 app->start;
1279
1280 While this is rather inefficient, as it prevents keep-alive, it is
1281 sometimes necessary for EventSource and similar applications.
1282
1283 HTTP/1.1 200 OK
1284 Date: Sat, 13 Sep 2014 16:48:29 GMT
1285 Connection: close
1286 Server: Mojolicious (Perl)
1287
1288 Hello World!
1289
1290 Chunked transfer encoding
1291 For very dynamic content you might not know the response content length
1292 in advance, that's where the chunked transfer encoding and
1293 "write_chunk" in Mojolicious::Controller come in handy. A common use
1294 would be to send the "head" section of an HTML document to the browser
1295 in advance and speed up preloading of referenced images and
1296 stylesheets.
1297
1298 use Mojolicious::Lite -signatures;
1299
1300 get '/' => sub ($c) {
1301 $c->write_chunk('<html><head><title>Example</title></head>' => sub ($c) {
1302 $c->finish('<body>Example</body></html>');
1303 });
1304 };
1305
1306 app->start;
1307
1308 The optional drain callback ensures that all previous chunks have been
1309 written before processing continues. To end the stream you can call
1310 "finish" in Mojolicious::Controller or write an empty chunk of data.
1311
1312 HTTP/1.1 200 OK
1313 Date: Sat, 13 Sep 2014 16:48:29 GMT
1314 Transfer-Encoding: chunked
1315 Server: Mojolicious (Perl)
1316
1317 29
1318 <html><head><title>Example</title></head>
1319 1b
1320 <body>Example</body></html>
1321 0
1322
1323 Especially in combination with long inactivity timeouts this can be
1324 very useful for Comet (long polling). Due to limitations in some web
1325 servers this might not work perfectly in all deployment environments.
1326
1327 Encoding
1328 Templates stored in files are expected to be "UTF-8" by default, but
1329 that can be easily changed with "encoding" in Mojolicious::Renderer.
1330
1331 $app->renderer->encoding('koi8-r');
1332
1333 All templates from the "DATA" section are bound to the encoding of the
1334 Perl script.
1335
1336 use Mojolicious::Lite;
1337
1338 get '/heart';
1339
1340 app->start;
1341 __DATA__
1342
1343 @@ heart.html.ep
1344 I ♥ Mojolicious!
1345
1346 Base64 encoded DATA files
1347 Base64 encoded static files such as images can be easily stored in the
1348 "DATA" section of your application, similar to templates.
1349
1350 use Mojolicious::Lite;
1351
1352 get '/' => {text => 'I ♥ Mojolicious!'};
1353
1354 app->start;
1355 __DATA__
1356
1357 @@ favicon.ico (base64)
1358 ...base64 encoded image...
1359
1360 Inflating DATA templates
1361 Templates stored in files get preferred over files from the "DATA"
1362 section, this allows you to include a default set of templates in your
1363 application that the user can later customize. The command
1364 Mojolicious::Command::Author::inflate will write all templates and
1365 static files from the "DATA" section into actual files in the
1366 "templates" and "public" directories.
1367
1368 $ ./myapp.pl inflate
1369
1370 Customizing the template syntax
1371 You can easily change the whole template syntax by loading
1372 Mojolicious::Plugin::EPRenderer with a custom configuration.
1373
1374 use Mojolicious::Lite;
1375
1376 plugin EPRenderer => {
1377 name => 'mustache',
1378 template => {
1379 tag_start => '{{',
1380 tag_end => '}}'
1381 }
1382 };
1383
1384 get '/:name' => {name => 'Anonymous'} => 'index';
1385
1386 app->start;
1387 __DATA__
1388
1389 @@ index.html.mustache
1390 Hello {{= $name }}.
1391
1392 Mojo::Template contains the whole list of available options.
1393
1394 Adding your favorite template system
1395 Maybe you would prefer a different template system than "ep", which is
1396 provided by Mojolicious::Plugin::EPRenderer, and there is not already a
1397 plugin on CPAN for your favorite one. All you have to do, is to add a
1398 new "handler" with "add_handler" in Mojolicious::Renderer when
1399 "register" is called.
1400
1401 package Mojolicious::Plugin::MyRenderer;
1402 use Mojo::Base 'Mojolicious::Plugin', -signatures;
1403
1404 sub register ($self, $app, $conf) {
1405
1406 # Add "mine" handler
1407 $app->renderer->add_handler(mine => sub ($renderer, $c, $output, $options) {
1408
1409 # Check for one-time use inline template
1410 my $inline_template = $options->{inline};
1411
1412 # Check for appropriate template in "templates" directories
1413 my $template_path = $renderer->template_path($options);
1414
1415 # Check for appropriate template in DATA sections
1416 my $data_template = $renderer->get_data_template($options);
1417
1418 # This part is up to you and your template system :)
1419 ...
1420
1421 # Pass the rendered result back to the renderer
1422 $$output = 'Hello World!';
1423
1424 # Or just die if an error occurs
1425 die 'Something went wrong with the template';
1426 });
1427 }
1428
1429 1;
1430
1431 An "inline" template, if provided by the user, will be passed along
1432 with the options. You can use "template_path" in Mojolicious::Renderer
1433 to search the "templates" directories of the application, and
1434 "get_data_template" in Mojolicious::Renderer to search the "DATA"
1435 sections.
1436
1437 use Mojolicious::Lite;
1438
1439 plugin 'MyRenderer';
1440
1441 # Render an inline template
1442 get '/inline' => {inline => '...', handler => 'mine'};
1443
1444 # Render a template from the DATA section
1445 get '/data' => {template => 'test'};
1446
1447 app->start;
1448 __DATA__
1449
1450 @@ test.html.mine
1451 ...
1452
1453 Adding a handler to generate binary data
1454 By default the renderer assumes that every "handler" generates
1455 characters that need to be automatically encoded, but this can be
1456 easily disabled if you're generating bytes instead.
1457
1458 use Mojolicious::Lite -signatures;
1459 use Storable qw(nfreeze);
1460
1461 # Add "storable" handler
1462 app->renderer->add_handler(storable => sub ($renderer, $c, $output, $options) {
1463
1464 # Disable automatic encoding
1465 delete $options->{encoding};
1466
1467 # Encode data from stash value
1468 $$output = nfreeze delete $c->stash->{storable};
1469 });
1470
1471 # Set "handler" value automatically if "storable" value is set already
1472 app->hook(before_render => sub ($c, $args) {
1473 $args->{handler} = 'storable' if exists $args->{storable} || exists $c->stash->{storable};
1474 });
1475
1476 get '/' => {storable => {i => '♥ mojolicious'}};
1477
1478 app->start;
1479
1480 The hook "before_render" in Mojolicious can be used to make stash
1481 values like "storable" special, so that they no longer require a
1482 "handler" value to be set explicitly.
1483
1484 # Explicit "handler" value
1485 $c->render(storable => {i => '♥ mojolicious'}, handler => 'storable');
1486
1487 # Implicit "handler" value (with "before_render" hook)
1488 $c->render(storable => {i => '♥ mojolicious'});
1489
1491 You can continue with Mojolicious::Guides now or take a look at the
1492 Mojolicious wiki <https://github.com/mojolicious/mojo/wiki>, which
1493 contains a lot more documentation and examples by many different
1494 authors.
1495
1497 If you have any questions the documentation might not yet answer, don't
1498 hesitate to ask in the Forum <https://forum.mojolicious.org> or the
1499 official IRC channel "#mojo" on "irc.libera.chat" (chat now!
1500 <https://web.libera.chat/#mojo>).
1501
1502
1503
1504perl v5.34.0 2022-01-21 Mojolicious::Guides::Rendering(3)