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
447 unless looks_like_number $dividend && looks_like_number $divisor;
448
449 # 500
450 return $c->reply->exception('Division by zero!') if $divisor == 0;
451
452 # 200
453 $c->render(text => $dividend / $divisor);
454 };
455
456 app->start;
457
458 To change the HTTP status code of the exception, you can use "rendered"
459 in Mojolicious::Controller.
460
461 return $c->reply->exception('Division by zero!')->rendered(400) if $divisor == 0;
462
463 You can also change the templates of those pages, since you most likely
464 want to show your users something more closely related to your
465 application in production. The renderer will always try to find
466 "exception.$mode.$format.*" or "not_found.$mode.$format.*" before
467 falling back to the built-in default templates.
468
469 use Mojolicious::Lite;
470
471 get '/dies' => sub { die 'Intentional error' };
472
473 app->start;
474 __DATA__
475
476 @@ exception.production.html.ep
477 <!DOCTYPE html>
478 <html>
479 <head><title>Server error</title></head>
480 <body>
481 <h1>Exception</h1>
482 <p><%= $exception->message %></p>
483 <h1>Stash</h1>
484 <pre><%= dumper $snapshot %></pre>
485 </body>
486 </html>
487
488 The hook "before_render" in Mojolicious makes even more advanced
489 customizations possible by allowing you to intercept and modify the
490 arguments passed to the renderer.
491
492 use Mojolicious::Lite -signatures;
493
494 hook before_render => sub ($c, $args) {
495
496 # Make sure we are rendering the exception template
497 return unless my $template = $args->{template};
498 return unless $template eq 'exception';
499
500 # Switch to JSON rendering if content negotiation allows it
501 return unless $c->accepts('json');
502 $args->{json} = {exception => $c->stash('exception')};
503 };
504
505 get '/' => sub { die "This sho...ALL GLORY TO THE HYPNOTOAD!\n" };
506
507 app->start;
508
509 Layouts
510 Most of the time when using "ep" templates you will want to wrap your
511 generated content in an HTML skeleton, thanks to layouts that's
512 absolutely trivial.
513
514 use Mojolicious::Lite;
515
516 get '/' => {template => 'foo/bar'};
517
518 app->start;
519 __DATA__
520
521 @@ foo/bar.html.ep
522 % layout 'mylayout';
523 Hello World!
524
525 @@ layouts/mylayout.html.ep
526 <!DOCTYPE html>
527 <html>
528 <head><title>MyApp</title></head>
529 <body><%= content %></body>
530 </html>
531
532 You just select the right layout template with the helper "layout" in
533 Mojolicious::Plugin::DefaultHelpers and place the result of the current
534 template with the helper "content" in
535 Mojolicious::Plugin::DefaultHelpers. You can also pass along normal
536 stash values to the "layout" helper.
537
538 use Mojolicious::Lite;
539
540 get '/' => {template => 'foo/bar'};
541
542 app->start;
543 __DATA__
544
545 @@ foo/bar.html.ep
546 % layout 'mylayout', title => 'Hi there';
547 Hello World!
548
549 @@ layouts/mylayout.html.ep
550 <!DOCTYPE html>
551 <html>
552 <head><title><%= $title %></title></head>
553 <body><%= content %></body>
554 </html>
555
556 Instead of the "layout" helper you could also just use the "layout"
557 stash value, or call "render" in Mojolicious::Controller with the
558 "layout" argument.
559
560 $c->render(template => 'mytemplate', layout => 'mylayout');
561
562 To set a "layout" stash value application-wide you can use "defaults"
563 in Mojolicious.
564
565 $app->defaults(layout => 'mylayout');
566
567 Layouts can also be used with "render_to_string" in
568 Mojolicious::Controller, but the "layout" value needs to be passed as a
569 render argument (not a stash value).
570
571 my $html = $c->render_to_string('reminder', layout => 'mail');
572
573 Partial templates
574 You can break up bigger templates into smaller, more manageable chunks.
575 These partial templates can also be shared with other templates. Just
576 use the helper "include" in Mojolicious::Plugin::DefaultHelpers to
577 include one template into another.
578
579 use Mojolicious::Lite;
580
581 get '/' => {template => 'foo/bar'};
582
583 app->start;
584 __DATA__
585
586 @@ foo/bar.html.ep
587 <!DOCTYPE html>
588 <html>
589 %= include '_header', title => 'Howdy'
590 <body>Bar</body>
591 </html>
592
593 @@ _header.html.ep
594 <head><title><%= $title %></title></head>
595
596 You can name partial templates however you like, but a leading
597 underscore is a commonly used naming convention.
598
599 Reusable template blocks
600 It's never fun to repeat yourself, that's why you can build reusable
601 template blocks in "ep" that work very similar to normal Perl
602 functions, with the "begin" and "end" keywords. Just be aware that both
603 keywords are part of the surrounding tag and not actual Perl code, so
604 there can only be whitespace after "begin" and before "end".
605
606 use Mojolicious::Lite;
607
608 get '/' => 'welcome';
609
610 app->start;
611 __DATA__
612
613 @@ welcome.html.ep
614 <% my $block = begin %>
615 % my $name = shift;
616 Hello <%= $name %>.
617 <% end %>
618 <%= $block->('Wolfgang') %>
619 <%= $block->('Baerbel') %>
620
621 A naive translation of the template to Perl code could look like this.
622
623 my $output = '';
624 my $block = sub ($name) {
625 my $output = '';
626 $output .= 'Hello ';
627 $output .= xml_escape scalar + $name;
628 $output .= '.';
629 return Mojo::ByteStream->new($output);
630 };
631 $output .= xml_escape scalar + $block->('Wolfgang');
632 $output .= xml_escape scalar + $block->('Baerbel');
633 return $output;
634
635 While template blocks cannot be shared between templates, they are most
636 commonly used to pass parts of a template to helpers.
637
638 Adding helpers
639 You should always try to keep your actions small and reuse as much code
640 as possible. Helpers make this very easy, they get passed the current
641 controller object as first argument, and you can use them to do pretty
642 much anything an action could do.
643
644 use Mojolicious::Lite -signatures;
645
646 helper debug => sub ($c, $str) {
647 $c->app->log->debug($str);
648 };
649
650 get '/' => sub ($c) {
651 $c->debug('Hello from an action!');
652 } => 'index';
653
654 app->start;
655 __DATA__
656
657 @@ index.html.ep
658 % debug 'Hello from a template!';
659
660 Helpers can also accept template blocks as last argument, this for
661 example, allows very pleasant to use tag helpers and filters. Wrapping
662 the helper result into a Mojo::ByteStream object can prevent accidental
663 double escaping.
664
665 use Mojolicious::Lite -signatures;
666 use Mojo::ByteStream;
667
668 helper trim_newline => sub ($c, $block) {
669 my $result = $block->();
670 $result =~ s/\n//g;
671 return Mojo::ByteStream->new($result);
672 };
673
674 get '/' => 'index';
675
676 app->start;
677 __DATA__
678
679 @@ index.html.ep
680 %= trim_newline begin
681 Some text.
682 %= 1 + 1
683 More text.
684 % end
685
686 Similar to stash values, you can use a prefix like "myapp.*" to keep
687 helpers from getting exposed in templates as functions, and to organize
688 them into namespaces as your application grows. Every prefix
689 automatically becomes a helper that returns a proxy object containing
690 the current controller object and on which you can call the nested
691 helpers.
692
693 use Mojolicious::Lite -signatures;
694
695 helper 'cache_control.no_caching' => sub ($c) { $c->res->headers->cache_control('private, max-age=0, no-cache') };
696 helper 'cache_control.five_minutes' => sub ($c) { $c->res->headers->cache_control('public, max-age=300') };
697
698 get '/news' => sub ($c) {
699 $c->cache_control->no_caching;
700 $c->render(text => 'Always up to date.');
701 };
702
703 get '/some_older_story' => sub ($c) {
704 $c->cache_control->five_minutes;
705 $c->render(text => 'This one can be cached for a bit.');
706 };
707
708 app->start;
709
710 While helpers can also be redefined, this should only be done very
711 carefully to avoid conflicts.
712
713 Content blocks
714 The helper "content_for" in Mojolicious::Plugin::DefaultHelpers allows
715 you to pass whole blocks of content from one template to another. This
716 can be very useful when your layout has distinct sections, such as
717 sidebars, where content should be inserted by the template.
718
719 use Mojolicious::Lite;
720
721 get '/' => 'foo';
722
723 app->start;
724 __DATA__
725
726 @@ foo.html.ep
727 % layout 'mylayout';
728 % content_for header => begin
729 <meta http-equiv="Content-Type" content="text/html">
730 % end
731 <div>Hello World!</div>
732 % content_for header => begin
733 <meta http-equiv="Pragma" content="no-cache">
734 % end
735
736 @@ layouts/mylayout.html.ep
737 <!DOCTYPE html>
738 <html>
739 <head><%= content 'header' %></head>
740 <body><%= content %></body>
741 </html>
742
743 Forms
744 To build HTML forms more efficiently you can use tag helpers like
745 "form_for" in Mojolicious::Plugin::TagHelpers, which can automatically
746 select a request method for you if a route name is provided. And since
747 most browsers only allow forms to be submitted with "GET" and "POST",
748 but not request methods like "PUT" or "DELETE", they are spoofed with
749 an "_method" query parameter.
750
751 use Mojolicious::Lite -signatures;
752
753 get '/' => 'form';
754
755 # PUT /nothing
756 # POST /nothing?_method=PUT
757 put '/nothing' => sub ($c) {
758
759 # Prevent double form submission with redirect
760 my $value = $c->param('whatever');
761 $c->flash(confirmation => "We did nothing with your value ($value).");
762 $c->redirect_to('form');
763 };
764
765 app->start;
766 __DATA__
767
768 @@ form.html.ep
769 <!DOCTYPE html>
770 <html>
771 <body>
772 % if (my $confirmation = flash 'confirmation') {
773 <p><%= $confirmation %></p>
774 % }
775 %= form_for nothing => begin
776 %= text_field whatever => 'I ♥ Mojolicious!'
777 %= submit_button
778 % end
779 </body>
780 </html>
781
782 The helpers "flash" in Mojolicious::Plugin::DefaultHelpers and
783 "redirect_to" in Mojolicious::Plugin::DefaultHelpers are often used
784 together to prevent double form submission, allowing users to receive a
785 confirmation message that will vanish if they decide to reload the page
786 they've been redirected to.
787
788 Form validation
789 You can use "validation" in Mojolicious::Plugin::DefaultHelpers to
790 validate "GET" and "POST" parameters submitted to your application. All
791 unknown fields will be ignored by default, so you have to decide which
792 should be required or optional before you can perform checks on their
793 values. Every check is performed right away, so you can use the results
794 immediately to build more advanced validation logic with methods like
795 "is_valid" in Mojolicious::Validator::Validation.
796
797 use Mojolicious::Lite -signatures;
798
799 get '/' => sub ($c) {
800
801 # Check if parameters have been submitted
802 my $v = $c->validation;
803 return $c->render('index') unless $v->has_data;
804
805 # Validate parameters ("pass_again" depends on "pass")
806 $v->required('user')->size(1, 20)->like(qr/^[a-z0-9]+$/);
807 $v->required('pass_again')->equal_to('pass')
808 if $v->optional('pass')->size(7, 500)->is_valid;
809
810 # Check if validation failed
811 return $c->render('index') if $v->has_error;
812
813 # Render confirmation
814 $c->render('thanks');
815 };
816
817 app->start;
818 __DATA__
819
820 @@ index.html.ep
821 <!DOCTYPE html>
822 <html>
823 <head>
824 <style>
825 label.field-with-error { color: #dd7e5e }
826 input.field-with-error { background-color: #fd9e7e }
827 </style>
828 </head>
829 <body>
830 %= form_for index => begin
831 %= label_for user => 'Username (required, 1-20 characters, a-z/0-9)'
832 <br>
833 %= text_field 'user', id => 'user'
834 %= submit_button
835 <br>
836 %= label_for pass => 'Password (optional, 7-500 characters)'
837 <br>
838 %= password_field 'pass', id => 'pass'
839 <br>
840 %= label_for pass_again => 'Password again (equal to the value above)'
841 <br>
842 %= password_field 'pass_again', id => 'pass_again'
843 % end
844 </body>
845 </html>
846
847 @@ thanks.html.ep
848 <!DOCTYPE html>
849 <html><body>Thank you <%= validation->param('user') %>.</body></html>
850
851 Form elements generated with tag helpers from
852 Mojolicious::Plugin::TagHelpers will automatically remember their
853 previous values and add the class "field-with-error" for fields that
854 failed validation to make styling with CSS easier.
855
856 <label class="field-with-error" for="user">
857 Username (required, only characters e-t)
858 </label>
859 <input class="field-with-error" type="text" name="user" value="sri">
860
861 For a full list of available checks see also "CHECKS" in
862 Mojolicious::Validator.
863
864 Adding form validation checks
865 Validation checks can be registered with "add_check" in
866 Mojolicious::Validator and return a false value if they were
867 successful. A true value may be used to pass along additional
868 information which can then be retrieved with "error" in
869 Mojolicious::Validator::Validation.
870
871 use Mojolicious::Lite -signatures;
872
873 # Add "range" check
874 app->validator->add_check(range => sub ($v, $name, $value, $min, $max) {
875 return $value < $min || $value > $max;
876 });
877
878 get '/' => 'form';
879
880 post '/test' => sub ($c) {
881
882 # Validate parameters with custom check
883 my $v = $c->validation;
884 $v->required('number')->range(3, 23);
885
886 # Render form again if validation failed
887 return $c->render('form') if $v->has_error;
888
889 # Prevent double form submission with redirect
890 $c->flash(number => $v->param('number'));
891 $c->redirect_to('form');
892 };
893
894 app->start;
895 __DATA__
896
897 @@ form.html.ep
898 <!DOCTYPE html>
899 <html>
900 <body>
901 % if (my $number = flash 'number') {
902 <p>Thanks, the number <%= $number %> was valid.</p>
903 % }
904 %= form_for test => begin
905 % if (my $err = validation->error('number')) {
906 <p>
907 %= 'Value is required.' if $err->[0] eq 'required'
908 %= 'Value needs to be between 3 and 23.' if $err->[0] eq 'range'
909 </p>
910 % }
911 %= text_field 'number'
912 %= submit_button
913 % end
914 </body>
915 </html>
916
917 Cross-site request forgery
918 CSRF is a very common attack on web applications that trick your logged
919 in users to submit forms they did not intend to send, with something as
920 mundane as a link. All you have to do, to protect your users from this,
921 is to add an additional hidden field to your forms with "csrf_field" in
922 Mojolicious::Plugin::TagHelpers, and validate it with "csrf_protect" in
923 Mojolicious::Validator::Validation.
924
925 use Mojolicious::Lite -signatures;
926
927 get '/' => {template => 'target'};
928
929 post '/' => sub ($c) {
930
931 # Check CSRF token
932 my $v = $c->validation;
933 return $c->render(text => 'Bad CSRF token!', status => 403) if $v->csrf_protect->has_error('csrf_token');
934
935 my $city = $v->required('city')->param('city');
936 $c->render(text => "Low orbit ion cannon pointed at $city!") unless $v->has_error;
937 } => 'target';
938
939 app->start;
940 __DATA__
941
942 @@ target.html.ep
943 <!DOCTYPE html>
944 <html>
945 <body>
946 %= form_for target => begin
947 %= csrf_field
948 %= label_for city => 'Which city to point low orbit ion cannon at?'
949 %= text_field 'city', id => 'city'
950 %= submit_button
951 %= end
952 </body>
953 </html>
954
955 For Ajax requests and the like, you can also generate a token directly
956 with the helper "csrf_token" in Mojolicious::Plugin::DefaultHelpers,
957 and then pass it along with the "X-CSRF-Token" request header.
958
960 Less commonly used and more powerful features.
961
962 Template inheritance
963 Inheritance takes the layout concept above one step further, the
964 helpers "content" in Mojolicious::Plugin::DefaultHelpers and "extends"
965 in Mojolicious::Plugin::DefaultHelpers allow you to build skeleton
966 templates with named blocks that child templates can override.
967
968 use Mojolicious::Lite;
969
970 # first > mylayout
971 get '/first' => {template => 'first', layout => 'mylayout'};
972
973 # third > second > first > mylayout
974 get '/third' => {template => 'third', layout => 'mylayout'};
975
976 app->start;
977 __DATA__
978
979 @@ layouts/mylayout.html.ep
980 <!DOCTYPE html>
981 <html>
982 <head><title>Hello</title></head>
983 <body><%= content %></body>
984 </html>
985
986 @@ first.html.ep
987 %= content header => begin
988 Default header
989 % end
990 <div>Hello World!</div>
991 %= content footer => begin
992 Default footer
993 % end
994
995 @@ second.html.ep
996 % extends 'first';
997 % content header => begin
998 New header
999 % end
1000
1001 @@ third.html.ep
1002 % extends 'second';
1003 % content footer => begin
1004 New footer
1005 % end
1006
1007 This chain could go on and on to allow a very high level of template
1008 reuse.
1009
1010 Serving static files
1011 Static files are automatically served from the "public" directories of
1012 the application, which can be customized with "paths" in
1013 Mojolicious::Static, or one of the "DATA" sections from "classes" in
1014 Mojolicious::Static. And if that's not enough you can also serve them
1015 manually with "reply->static" in Mojolicious::Plugin::DefaultHelpers
1016 and "reply->file" in Mojolicious::Plugin::DefaultHelpers.
1017
1018 use Mojolicious::Lite -signatures;
1019
1020 get '/' => sub ($c) {
1021 $c->reply->static('index.html');
1022 };
1023
1024 get '/some_download' => sub ($c) {
1025 $c->res->headers->content_disposition('attachment; filename=bar.png;');
1026 $c->reply->static('foo/bar.png');
1027 };
1028
1029 get '/leak' => sub ($c) {
1030 $c->reply->file('/etc/passwd');
1031 };
1032
1033 app->start;
1034
1035 Custom responses
1036 Most response content, static as well as dynamic, gets served through
1037 Mojo::Asset::File and Mojo::Asset::Memory objects. For somewhat static
1038 content, like cached JSON data or temporary files, you can create your
1039 own and use the helper "reply->asset" in
1040 Mojolicious::Plugin::DefaultHelpers to serve them while allowing
1041 content negotiation to be performed with "Range", "If-Modified-Since"
1042 and "If-None-Match" headers.
1043
1044 use Mojolicious::Lite -signatures;
1045 use Mojo::Asset::File;
1046
1047 get '/leak' => sub ($c) {
1048 $c->res->headers->content_type('text/plain');
1049 $c->reply->asset(Mojo::Asset::File->new(path => '/etc/passwd'));
1050 };
1051
1052 app->start;
1053
1054 For even more control you can also just skip the helper and use
1055 "rendered" in Mojolicious::Controller to tell the renderer when you're
1056 done generating a response.
1057
1058 use Mojolicious::Lite -signatures;
1059 use Mojo::Asset::File;
1060
1061 get '/leak' => sub ($c) {
1062 $c->res->headers->content_type('text/plain');
1063 $c->res->content->asset(Mojo::Asset::File->new(path => '/etc/passwd'));
1064 $c->rendered(200);
1065 };
1066
1067 app->start;
1068
1069 Helper plugins
1070 Some helpers might be useful enough for you to share them between
1071 multiple applications, plugins make that very simple.
1072
1073 package Mojolicious::Plugin::DebugHelper;
1074 use Mojo::Base 'Mojolicious::Plugin', -signatures;
1075
1076 sub register ($self, $app, $conf) {
1077 $app->helper(debug => sub ($c, $str) {
1078 $c->app->log->debug($str);
1079 });
1080 }
1081
1082 1;
1083
1084 The "register" method will be called when you load the plugin. And to
1085 add your helper to the application, you can use "helper" in
1086 Mojolicious.
1087
1088 use Mojolicious::Lite -signatures;
1089
1090 plugin 'DebugHelper';
1091
1092 get '/' => sub ($c) {
1093 $c->debug('It works!');
1094 $c->render(text => 'Hello!');
1095 };
1096
1097 app->start;
1098
1099 A skeleton for a full CPAN compatible plugin distribution can be
1100 automatically generated.
1101
1102 $ mojo generate plugin DebugHelper
1103
1104 And if you have a "PAUSE" account (which can be requested at
1105 <http://pause.perl.org>), you are only a few commands away from
1106 releasing it to CPAN.
1107
1108 $ perl Makefile.PL
1109 $ make test
1110 $ make manifest
1111 $ make dist
1112 $ mojo cpanify -u USER -p PASS Mojolicious-Plugin-DebugHelper-0.01.tar.gz
1113
1114 Bundling assets with plugins
1115 Assets such as templates and static files can be easily bundled with
1116 your plugins, even if you plan to release them to CPAN.
1117
1118 $ mojo generate plugin AlertAssets
1119 $ mkdir Mojolicious-Plugin-AlertAssets/lib/Mojolicious/Plugin/AlertAssets
1120 $ cd Mojolicious-Plugin-AlertAssets/lib/Mojolicious/Plugin/AlertAssets
1121 $ mkdir public
1122 $ echo 'alert("Hello World!");' > public/alertassets.js
1123 $ mkdir templates
1124 $ echo '%= javascript "/alertassets.js"' > templates/alertassets.html.ep
1125
1126 Just give them reasonably unique names, ideally based on the name of
1127 your plugin, and append their respective directories to the list of
1128 search paths when "register" is called.
1129
1130 package Mojolicious::Plugin::AlertAssets;
1131 use Mojo::Base 'Mojolicious::Plugin', -signatures;
1132
1133 use Mojo::File qw(curfile);
1134
1135 sub register ($self, $app, $conf) {
1136
1137 # Append "templates" and "public" directories
1138 my $base = curfile->sibling('AlertAssets');
1139 push @{$app->renderer->paths}, $base->child('templates')->to_string;
1140 push @{$app->static->paths}, $base->child('public')->to_string;
1141 }
1142
1143 1;
1144
1145 Both will work just like normal "templates" and "public" directories
1146 once you've installed and loaded the plugin, with slightly lower
1147 precedence.
1148
1149 use Mojolicious::Lite;
1150
1151 plugin 'AlertAssets';
1152
1153 get '/alert_me';
1154
1155 app->start;
1156 __DATA__
1157
1158 @@ alert_me.html.ep
1159 <!DOCTYPE html>
1160 <html>
1161 <head>
1162 <title>Alert me!</title>
1163 %= include 'alertassets'
1164 </head>
1165 <body>You've been alerted.</body>
1166 </html>
1167
1168 And it works just the same for assets bundled in the "DATA" section of
1169 your plugin.
1170
1171 package Mojolicious::Plugin::AlertAssets;
1172 use Mojo::Base 'Mojolicious::Plugin', -signatures;
1173
1174 sub register ($self, $app, $conf) {
1175
1176 # Append class
1177 push @{$app->renderer->classes}, __PACKAGE__;
1178 push @{$app->static->classes}, __PACKAGE__;
1179 }
1180
1181 1;
1182 __DATA__
1183
1184 @@ alertassets.js
1185 alert("Hello World!");
1186
1187 @@ alertassets.html.ep
1188 %= javascript "/alertassets.js"
1189
1190 Post-processing dynamic content
1191 While post-processing tasks are generally very easy with the hook
1192 "after_dispatch" in Mojolicious, for content generated by the renderer
1193 it is a lot more efficient to use "after_render" in Mojolicious.
1194
1195 use Mojolicious::Lite -signatures;
1196 use IO::Compress::Gzip qw(gzip);
1197
1198 hook after_render => sub ($c, $output, $format) {
1199
1200 # Check if "gzip => 1" has been set in the stash
1201 return unless $c->stash->{gzip};
1202
1203 # Check if user agent accepts gzip compression
1204 return unless ($c->req->headers->accept_encoding // '') =~ /gzip/i;
1205 $c->res->headers->append(Vary => 'Accept-Encoding');
1206
1207 # Compress content with gzip
1208 $c->res->headers->content_encoding('gzip');
1209 gzip $output, \my $compressed;
1210 $$output = $compressed;
1211 };
1212
1213 get '/' => {template => 'hello', title => 'Hello', gzip => 1};
1214
1215 app->start;
1216 __DATA__
1217
1218 @@ hello.html.ep
1219 <!DOCTYPE html>
1220 <html>
1221 <head><title><%= title %></title></head>
1222 <body>Compressed content.</body>
1223 </html>
1224
1225 If you want to compress all dynamically generated content you can also
1226 activate "compress" in Mojolicious::Renderer.
1227
1228 Streaming
1229 You don't have to render all content at once, the method "write" in
1230 Mojolicious::Controller can also be used to stream a series of smaller
1231 chunks.
1232
1233 use Mojolicious::Lite -signatures;
1234
1235 get '/' => sub ($c) {
1236
1237 # Prepare body
1238 my $body = 'Hello World!';
1239 $c->res->headers->content_length(length $body);
1240
1241 # Start writing directly with a drain callback
1242 my $drain = sub ($c) {
1243 my $chunk = substr $body, 0, 1, '';
1244 $c->write($chunk, length $body ? __SUB__ : undef);
1245 };
1246 $c->$drain;
1247 };
1248
1249 app->start;
1250
1251 The drain callback will be executed whenever the entire previous chunk
1252 of data has actually been written.
1253
1254 HTTP/1.1 200 OK
1255 Date: Sat, 13 Sep 2014 16:48:29 GMT
1256 Content-Length: 12
1257 Server: Mojolicious (Perl)
1258
1259 Hello World!
1260
1261 Instead of providing a "Content-Length" header you can also call
1262 "finish" in Mojolicious::Controller and close the connection manually
1263 once you are done.
1264
1265 use Mojolicious::Lite -signatures;
1266
1267 get '/' => sub ($c) {
1268
1269 # Prepare body
1270 my $body = 'Hello World!';
1271
1272 # Start writing directly with a drain callback
1273 my $drain = sub ($c) {
1274 my $chunk = substr $body, 0, 1, '';
1275 length $chunk ? $c->write($chunk, __SUB__) : $c->finish;
1276 };
1277 $c->$drain;
1278 };
1279
1280 app->start;
1281
1282 While this is rather inefficient, as it prevents keep-alive, it is
1283 sometimes necessary for EventSource and similar applications.
1284
1285 HTTP/1.1 200 OK
1286 Date: Sat, 13 Sep 2014 16:48:29 GMT
1287 Connection: close
1288 Server: Mojolicious (Perl)
1289
1290 Hello World!
1291
1292 Chunked transfer encoding
1293 For very dynamic content you might not know the response content length
1294 in advance, that's where the chunked transfer encoding and
1295 "write_chunk" in Mojolicious::Controller come in handy. A common use
1296 would be to send the "head" section of an HTML document to the browser
1297 in advance and speed up preloading of referenced images and
1298 stylesheets.
1299
1300 use Mojolicious::Lite -signatures;
1301
1302 get '/' => sub ($c) {
1303 $c->write_chunk('<html><head><title>Example</title></head>' => sub ($c) {
1304 $c->finish('<body>Example</body></html>');
1305 });
1306 };
1307
1308 app->start;
1309
1310 The optional drain callback ensures that all previous chunks have been
1311 written before processing continues. To end the stream you can call
1312 "finish" in Mojolicious::Controller or write an empty chunk of data.
1313
1314 HTTP/1.1 200 OK
1315 Date: Sat, 13 Sep 2014 16:48:29 GMT
1316 Transfer-Encoding: chunked
1317 Server: Mojolicious (Perl)
1318
1319 29
1320 <html><head><title>Example</title></head>
1321 1b
1322 <body>Example</body></html>
1323 0
1324
1325 Especially in combination with long inactivity timeouts this can be
1326 very useful for Comet (long polling). Due to limitations in some web
1327 servers this might not work perfectly in all deployment environments.
1328
1329 Encoding
1330 Templates stored in files are expected to be "UTF-8" by default, but
1331 that can be easily changed with "encoding" in Mojolicious::Renderer.
1332
1333 $app->renderer->encoding('koi8-r');
1334
1335 All templates from the "DATA" section are bound to the encoding of the
1336 Perl script.
1337
1338 use Mojolicious::Lite;
1339
1340 get '/heart';
1341
1342 app->start;
1343 __DATA__
1344
1345 @@ heart.html.ep
1346 I ♥ Mojolicious!
1347
1348 Base64 encoded DATA files
1349 Base64 encoded static files such as images can be easily stored in the
1350 "DATA" section of your application, similar to templates.
1351
1352 use Mojolicious::Lite;
1353
1354 get '/' => {text => 'I ♥ Mojolicious!'};
1355
1356 app->start;
1357 __DATA__
1358
1359 @@ favicon.ico (base64)
1360 ...base64 encoded image...
1361
1362 Inflating DATA templates
1363 Templates stored in files get preferred over files from the "DATA"
1364 section, this allows you to include a default set of templates in your
1365 application that the user can later customize. The command
1366 Mojolicious::Command::Author::inflate will write all templates and
1367 static files from the "DATA" section into actual files in the
1368 "templates" and "public" directories.
1369
1370 $ ./myapp.pl inflate
1371
1372 Customizing the template syntax
1373 You can easily change the whole template syntax by loading
1374 Mojolicious::Plugin::EPRenderer with a custom configuration.
1375
1376 use Mojolicious::Lite;
1377
1378 plugin EPRenderer => {
1379 name => 'mustache',
1380 template => {
1381 tag_start => '{{',
1382 tag_end => '}}'
1383 }
1384 };
1385
1386 get '/:name' => {name => 'Anonymous'} => 'index';
1387
1388 app->start;
1389 __DATA__
1390
1391 @@ index.html.mustache
1392 Hello {{= $name }}.
1393
1394 Mojo::Template contains the whole list of available options.
1395
1396 Adding your favorite template system
1397 Maybe you would prefer a different template system than "ep", which is
1398 provided by Mojolicious::Plugin::EPRenderer, and there is not already a
1399 plugin on CPAN for your favorite one. All you have to do, is to add a
1400 new "handler" with "add_handler" in Mojolicious::Renderer when
1401 "register" is called.
1402
1403 package Mojolicious::Plugin::MyRenderer;
1404 use Mojo::Base 'Mojolicious::Plugin', -signatures;
1405
1406 sub register ($self, $app, $conf) {
1407
1408 # Add "mine" handler
1409 $app->renderer->add_handler(mine => sub ($renderer, $c, $output, $options) {
1410
1411 # Check for one-time use inline template
1412 my $inline_template = $options->{inline};
1413
1414 # Check for appropriate template in "templates" directories
1415 my $template_path = $renderer->template_path($options);
1416
1417 # Check for appropriate template in DATA sections
1418 my $data_template = $renderer->get_data_template($options);
1419
1420 # This part is up to you and your template system :)
1421 ...
1422
1423 # Pass the rendered result back to the renderer
1424 $$output = 'Hello World!';
1425
1426 # Or just die if an error occurs
1427 die 'Something went wrong with the template';
1428 });
1429 }
1430
1431 1;
1432
1433 An "inline" template, if provided by the user, will be passed along
1434 with the options. You can use "template_path" in Mojolicious::Renderer
1435 to search the "templates" directories of the application, and
1436 "get_data_template" in Mojolicious::Renderer to search the "DATA"
1437 sections.
1438
1439 use Mojolicious::Lite;
1440
1441 plugin 'MyRenderer';
1442
1443 # Render an inline template
1444 get '/inline' => {inline => '...', handler => 'mine'};
1445
1446 # Render a template from the DATA section
1447 get '/data' => {template => 'test'};
1448
1449 app->start;
1450 __DATA__
1451
1452 @@ test.html.mine
1453 ...
1454
1455 Adding a handler to generate binary data
1456 By default the renderer assumes that every "handler" generates
1457 characters that need to be automatically encoded, but this can be
1458 easily disabled if you're generating bytes instead.
1459
1460 use Mojolicious::Lite -signatures;
1461 use Storable qw(nfreeze);
1462
1463 # Add "storable" handler
1464 app->renderer->add_handler(storable => sub ($renderer, $c, $output, $options) {
1465
1466 # Disable automatic encoding
1467 delete $options->{encoding};
1468
1469 # Encode data from stash value
1470 $$output = nfreeze delete $c->stash->{storable};
1471 });
1472
1473 # Set "handler" value automatically if "storable" value is set already
1474 app->hook(before_render => sub ($c, $args) {
1475 $args->{handler} = 'storable' if exists $args->{storable} || exists $c->stash->{storable};
1476 });
1477
1478 get '/' => {storable => {i => '♥ mojolicious'}};
1479
1480 app->start;
1481
1482 The hook "before_render" in Mojolicious can be used to make stash
1483 values like "storable" special, so that they no longer require a
1484 "handler" value to be set explicitly.
1485
1486 # Explicit "handler" value
1487 $c->render(storable => {i => '♥ mojolicious'}, handler => 'storable');
1488
1489 # Implicit "handler" value (with "before_render" hook)
1490 $c->render(storable => {i => '♥ mojolicious'});
1491
1493 You can continue with Mojolicious::Guides now or take a look at the
1494 Mojolicious wiki <https://github.com/mojolicious/mojo/wiki>, which
1495 contains a lot more documentation and examples by many different
1496 authors.
1497
1499 If you have any questions the documentation might not yet answer, don't
1500 hesitate to ask in the Forum <https://forum.mojolicious.org> or the
1501 official IRC channel "#mojo" on "chat.freenode.net" (chat now!
1502 <https://webchat.freenode.net/#mojo>).
1503
1504
1505
1506perl v5.32.1 2021-02-07 Mojolicious::Guides::Rendering(3)