1Mojolicious::Guides::ReUnsdeerriCnogn(t3r)ibuted Perl DoMcoujmoelnitcaitoiuosn::Guides::Rendering(3)
2
3
4

NAME

6       Mojolicious::Guides::Rendering - Rendering content
7

OVERVIEW

9       This document explains content generation with the Mojolicious
10       renderer.
11

CONCEPTS

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

BASICS

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', 'mojo.js']);
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   Static files
360       Static files are automatically served from the "public" directories of
361       the application, which can be customized with "paths" in
362       Mojolicious::Static, or one of the "DATA" sections from "classes" in
363       Mojolicious::Static. And if that's not enough you can also serve them
364       manually with "reply->static" in Mojolicious::Plugin::DefaultHelpers
365       and "reply->file" in Mojolicious::Plugin::DefaultHelpers.
366
367         use Mojolicious::Lite -signatures;
368
369         get '/' => sub ($c) {
370           $c->reply->static('index.html');
371         };
372
373         get '/some_download' => sub ($c) {
374           $c->res->headers->content_disposition('attachment; filename=bar.png;');
375           $c->reply->static('foo/bar.png');
376         };
377
378         get '/leak' => sub ($c) {
379           $c->reply->file('/etc/passwd');
380         };
381
382         app->start;
383
384   Static assets
385       While Mojolicious does not have any special support for frontend
386       frameworks like Vue.js <https://vuejs.org> and React
387       <https://reactjs.org>, the "public/assets" directory is reserved for
388       static assets created by bundlers like Webpack <https://webpack.js.org>
389       and Rollup.js <https://rollupjs.org> ahead of time. Asset files can be
390       of any type, they just have to follow the
391       "[name].[checksum].[extensions]" naming scheme, like
392       "myapp.ab1234cd5678ef.js". You can then use "url_for_asset" in
393       Mojolicious::Controller or "asset_tag" in
394       Mojolicious::Plugin::TagHelpers to generate URLs without having to know
395       the checksum.
396
397         # "/assets/myapp.ab1234cd5678ef.js"
398         $c->url_for_asset('/myapp.js');
399
400         # "<script src="/assets/myapp.ab1234cd5678ef.js"></script>"
401         $c->asset_tag('/myapp.js');
402
403       If your application runs in "development" mode, all assets will be
404       served with a "Cache-Control: no-cache" header, to speed up development
405       by preventing browser caching. Additionally all assets following the
406       "[name].development.[extensions]" naming scheme, like
407       "myapp.development.js", have a higher precedence than assets with
408       checksums. That way you can just overwrite your assets during
409       development, instead of having to manually delete them each time they
410       are rebuilt with a different checksum.
411
412         # "/assets/foo/bar.development.js"
413         $c->url_for_asset('/foo/bar.js');
414
415       Webpack configuration <https://webpack.js.org/configuration/> example
416       ("webpack.config.js"):
417
418         import Path from '@mojojs/path';
419
420         const isDev = process.env.MOJO_MODE === 'development';
421
422         export default {
423           output: {
424             filename: isDev ? '[name].development.js' : '[name].[chunkhash].js',
425             path: Path.currentFile().sibling('public', 'assets').toString(),
426             publicPath: ''
427           },
428
429           // Add your own rules and entry point here
430         };
431
432       Rollup configuration <https://rollupjs.org/guide/en/#configuration-
433       files> example ("rollup.config.js"):
434
435         import Path from '@mojojs/path';
436
437         const isDev = process.env.MOJO_MODE === 'development';
438
439         export default {
440           output: {
441             entryFileNames: isDev ? '[name].development.[ext]' : '[name].[hash].[ext]',
442             dir: Path.currentFile().sibling('public', 'assets').toString(),
443             format: 'iife'
444           },
445
446           // Add your own rules and entry point here
447         };
448
449       Everything else is up to your bundler of choice, so you need to consult
450       its documentation for further information. And where you keep your
451       asset sources, such as ".vue" and ".jsx" files, is not important, as
452       long as your bundler can find them. Using a directory named "assets" or
453       "frontend" in your application root directory is a good best practice
454       though.
455
456   Content negotiation
457       For resources with different representations and that require truly
458       RESTful content negotiation you can also use "respond_to" in
459       Mojolicious::Plugin::DefaultHelpers instead of "render" in
460       Mojolicious::Controller.
461
462         # /hello (Accept: application/json) -> "json"
463         # /hello (Accept: application/xml)  -> "xml"
464         # /hello.json                       -> "json"
465         # /hello.xml                        -> "xml"
466         # /hello?_format=json               -> "json"
467         # /hello?_format=xml                -> "xml"
468         $c->respond_to(
469           json => {json => {hello => 'world'}},
470           xml  => {text => '<hello>world</hello>'}
471         );
472
473       The best possible representation will be automatically selected from
474       the "_format" "GET"/"POST" parameter, "format" stash value or "Accept"
475       request header and stored in the "format" stash value. To change MIME
476       type mappings for the "Accept" request header or the "Content-Type"
477       response header you can use "types" in Mojolicious.
478
479         $c->respond_to(
480           json => {json => {hello => 'world'}},
481           html => sub {
482             $c->content_for(head => '<meta name="author" content="sri">');
483             $c->render(template => 'hello', message => 'world')
484           }
485         );
486
487       Callbacks can be used for representations that are too complex to fit
488       into a single render call.
489
490         # /hello (Accept: application/json) -> "json"
491         # /hello (Accept: text/html)        -> "html"
492         # /hello (Accept: image/png)        -> "any"
493         # /hello.json                       -> "json"
494         # /hello.html                       -> "html"
495         # /hello.png                        -> "any"
496         # /hello?_format=json                -> "json"
497         # /hello?_format=html                -> "html"
498         # /hello?_format=png                 -> "any"
499         $c->respond_to(
500           json => {json => {hello => 'world'}},
501           html => {template => 'hello', message => 'world'},
502           any  => {text => '', status => 204}
503         );
504
505       And if no viable representation could be found, the "any" fallback will
506       be used or an empty 204 response rendered automatically.
507
508         # /hello                      -> "html"
509         # /hello (Accept: text/html)  -> "html"
510         # /hello (Accept: text/xml)   -> "xml"
511         # /hello (Accept: text/plain) -> undef
512         # /hello.html                 -> "html"
513         # /hello.xml                  -> "xml"
514         # /hello.txt                  -> undef
515         # /hello?_format=html          -> "html"
516         # /hello?_format=xml           -> "xml"
517         # /hello?_format=txt           -> undef
518         if (my $format = $c->accepts('html', 'xml')) {
519           ...
520         }
521
522       For even more advanced negotiation logic you can also use the helper
523       "accepts" in Mojolicious::Plugin::DefaultHelpers.
524
525   Rendering "exception" and "not_found" pages
526       By now you've probably already encountered the built-in 404 (Not Found)
527       and 500 (Server Error) pages, that get rendered automatically when you
528       make a mistake. Those are fallbacks for when your own exception
529       handling fails, which can be especially helpful during development. You
530       can also render them manually with the helpers "reply->exception" in
531       Mojolicious::Plugin::DefaultHelpers and "reply->not_found" in
532       Mojolicious::Plugin::DefaultHelpers.
533
534         use Mojolicious::Lite -signatures;
535         use Scalar::Util qw(looks_like_number);
536
537         get '/divide/:dividend/by/:divisor' => sub ($c) {
538
539           my $dividend = $c->param('dividend');
540           my $divisor  = $c->param('divisor');
541
542           # 404
543           return $c->reply->not_found unless looks_like_number $dividend && looks_like_number $divisor;
544
545           # 500
546           return $c->reply->exception('Division by zero!') if $divisor == 0;
547
548           # 200
549           $c->render(text => $dividend / $divisor);
550         };
551
552         app->start;
553
554       To change the HTTP status code of the exception, you can use "rendered"
555       in Mojolicious::Controller.
556
557         return $c->reply->exception('Division by zero!')->rendered(400) if $divisor == 0;
558
559       You can also change the templates of those pages, since you most likely
560       want to show your users something more closely related to your
561       application in production. The renderer will always try to find
562       "exception.$mode.$format.*" or "not_found.$mode.$format.*" before
563       falling back to the built-in default templates.
564
565         use Mojolicious::Lite;
566
567         get '/dies' => sub { die 'Intentional error' };
568
569         app->start;
570         __DATA__
571
572         @@ exception.production.html.ep
573         <!DOCTYPE html>
574         <html>
575           <head><title>Server error</title></head>
576           <body>
577             <h1>Exception</h1>
578             <p><%= $exception->message %></p>
579             <h1>Stash</h1>
580             <pre><%= dumper $snapshot %></pre>
581           </body>
582         </html>
583
584       The default exception format is "html", but that can be changed at
585       application and controller level. By default there are handlers for
586       "html", "txt" and "json" available. There are also various exception
587       helpers in Mojolicious::Plugin::DefaultHelpers for you to overload to
588       change the default behavior.
589
590         use Mojolicious::Lite -signatures;
591
592         app->exception_format('json');
593
594         get '/json' => sub ($c) {
595           die 'Just a test';
596         };
597
598         get '/txt' => sub ($c) {
599           $c->exception_format('txt');
600           die 'Just a test';
601         };
602
603         app->start;
604
605       The hook "before_render" in Mojolicious makes even more advanced
606       customizations possible by allowing you to intercept and modify the
607       arguments passed to the renderer.
608
609         use Mojolicious::Lite -signatures;
610
611         hook before_render => sub ($c, $args) {
612
613           # Make sure we are rendering the exception template
614           return unless my $template = $args->{template};
615           return unless $template eq 'exception';
616
617           # Switch to JSON rendering if content negotiation allows it
618           return unless $c->accepts('json');
619           $args->{json} = {exception => $c->stash('exception')};
620         };
621
622         get '/' => sub { die "This sho...ALL GLORY TO THE HYPNOTOAD!\n" };
623
624         app->start;
625
626   Layouts
627       Most of the time when using "ep" templates you will want to wrap your
628       generated content in an HTML skeleton, thanks to layouts that's
629       absolutely trivial.
630
631         use Mojolicious::Lite;
632
633         get '/' => {template => 'foo/bar'};
634
635         app->start;
636         __DATA__
637
638         @@ foo/bar.html.ep
639         % layout 'mylayout';
640         Hello World!
641
642         @@ layouts/mylayout.html.ep
643         <!DOCTYPE html>
644         <html>
645           <head><title>MyApp</title></head>
646           <body><%= content %></body>
647         </html>
648
649       You just select the right layout template with the helper "layout" in
650       Mojolicious::Plugin::DefaultHelpers and place the result of the current
651       template with the helper "content" in
652       Mojolicious::Plugin::DefaultHelpers. You can also pass along normal
653       stash values to the "layout" helper.
654
655         use Mojolicious::Lite;
656
657         get '/' => {template => 'foo/bar'};
658
659         app->start;
660         __DATA__
661
662         @@ foo/bar.html.ep
663         % layout 'mylayout', title => 'Hi there';
664         Hello World!
665
666         @@ layouts/mylayout.html.ep
667         <!DOCTYPE html>
668         <html>
669           <head><title><%= $title %></title></head>
670           <body><%= content %></body>
671         </html>
672
673       Instead of the "layout" helper you could also just use the "layout"
674       stash value, or call "render" in Mojolicious::Controller with the
675       "layout" argument.
676
677         $c->render(template => 'mytemplate', layout => 'mylayout');
678
679       To set a "layout" stash value application-wide you can use "defaults"
680       in Mojolicious.
681
682         $app->defaults(layout => 'mylayout');
683
684       Layouts can also be used with "render_to_string" in
685       Mojolicious::Controller, but the "layout" value needs to be passed as a
686       render argument (not a stash value).
687
688         my $html = $c->render_to_string('reminder', layout => 'mail');
689
690   Partial templates
691       You can break up bigger templates into smaller, more manageable chunks.
692       These partial templates can also be shared with other templates. Just
693       use the helper "include" in Mojolicious::Plugin::DefaultHelpers to
694       include one template into another.
695
696         use Mojolicious::Lite;
697
698         get '/' => {template => 'foo/bar'};
699
700         app->start;
701         __DATA__
702
703         @@ foo/bar.html.ep
704         <!DOCTYPE html>
705         <html>
706           %= include '_header', title => 'Howdy'
707           <body>Bar</body>
708         </html>
709
710         @@ _header.html.ep
711         <head><title><%= $title %></title></head>
712
713       You can name partial templates however you like, but a leading
714       underscore is a commonly used naming convention.
715
716   Reusable template blocks
717       It's never fun to repeat yourself, that's why you can build reusable
718       template blocks in "ep" that work very similar to normal Perl
719       functions, with the "begin" and "end" keywords. Just be aware that both
720       keywords are part of the surrounding tag and not actual Perl code, so
721       there can only be whitespace after "begin" and before "end".
722
723         use Mojolicious::Lite;
724
725         get '/' => 'welcome';
726
727         app->start;
728         __DATA__
729
730         @@ welcome.html.ep
731         <% my $block = begin %>
732           % my $name = shift;
733           Hello <%= $name %>.
734         <% end %>
735         <%= $block->('Wolfgang') %>
736         <%= $block->('Baerbel') %>
737
738       A naive translation of the template to Perl code could look like this.
739
740         my $output = '';
741         my $block  = sub ($name) {
742           my $output = '';
743           $output .= 'Hello ';
744           $output .= xml_escape scalar + $name;
745           $output .= '.';
746           return Mojo::ByteStream->new($output);
747         };
748         $output .= xml_escape scalar + $block->('Wolfgang');
749         $output .= xml_escape scalar + $block->('Baerbel');
750         return $output;
751
752       While template blocks cannot be shared between templates, they are most
753       commonly used to pass parts of a template to helpers.
754
755   Adding helpers
756       You should always try to keep your actions small and reuse as much code
757       as possible. Helpers make this very easy, they get passed the current
758       controller object as first argument, and you can use them to do pretty
759       much anything an action could do.
760
761         use Mojolicious::Lite -signatures;
762
763         helper debug => sub ($c, $str) {
764           $c->app->log->debug($str);
765         };
766
767         get '/' => sub ($c) {
768           $c->debug('Hello from an action!');
769         } => 'index';
770
771         app->start;
772         __DATA__
773
774         @@ index.html.ep
775         % debug 'Hello from a template!';
776
777       Helpers can also accept template blocks as last argument, this for
778       example, allows very pleasant to use tag helpers and filters. Wrapping
779       the helper result into a Mojo::ByteStream object can prevent accidental
780       double escaping.
781
782         use Mojolicious::Lite -signatures;
783         use Mojo::ByteStream;
784
785         helper trim_newline => sub ($c, $block) {
786           my $result = $block->();
787           $result =~ s/\n//g;
788           return Mojo::ByteStream->new($result);
789         };
790
791         get '/' => 'index';
792
793         app->start;
794         __DATA__
795
796         @@ index.html.ep
797         %= trim_newline begin
798           Some text.
799           %= 1 + 1
800           More text.
801         % end
802
803       Similar to stash values, you can use a prefix like "myapp.*" to keep
804       helpers from getting exposed in templates as functions, and to organize
805       them into namespaces as your application grows. Every prefix
806       automatically becomes a helper that returns a proxy object containing
807       the current controller object and on which you can call the nested
808       helpers.
809
810         use Mojolicious::Lite -signatures;
811
812         helper 'cache_control.no_caching'   => sub ($c) { $c->res->headers->cache_control('private, max-age=0, no-cache') };
813         helper 'cache_control.five_minutes' => sub ($c) { $c->res->headers->cache_control('public, max-age=300') };
814
815         get '/news' => sub ($c) {
816           $c->cache_control->no_caching;
817           $c->render(text => 'Always up to date.');
818         };
819
820         get '/some_older_story' => sub ($c) {
821           $c->cache_control->five_minutes;
822           $c->render(text => 'This one can be cached for a bit.');
823         };
824
825         app->start;
826
827       While helpers can also be redefined, this should only be done very
828       carefully to avoid conflicts.
829
830   Content blocks
831       The helper "content_for" in Mojolicious::Plugin::DefaultHelpers allows
832       you to pass whole blocks of content from one template to another. This
833       can be very useful when your layout has distinct sections, such as
834       sidebars, where content should be inserted by the template.
835
836         use Mojolicious::Lite;
837
838         get '/' => 'foo';
839
840         app->start;
841         __DATA__
842
843         @@ foo.html.ep
844         % layout 'mylayout';
845         % content_for header => begin
846           <meta http-equiv="Content-Type" content="text/html">
847         % end
848         <div>Hello World!</div>
849         % content_for header => begin
850           <meta http-equiv="Pragma" content="no-cache">
851         % end
852
853         @@ layouts/mylayout.html.ep
854         <!DOCTYPE html>
855         <html>
856           <head><%= content 'header' %></head>
857           <body><%= content %></body>
858         </html>
859
860   Forms
861       To build HTML forms more efficiently you can use tag helpers like
862       "form_for" in Mojolicious::Plugin::TagHelpers, which can automatically
863       select a request method for you if a route name is provided. And since
864       most browsers only allow forms to be submitted with "GET" and "POST",
865       but not request methods like "PUT" or "DELETE", they are spoofed with
866       an "_method" query parameter.
867
868         use Mojolicious::Lite -signatures;
869
870         get '/' => 'form';
871
872         # PUT  /nothing
873         # POST /nothing?_method=PUT
874         put '/nothing' => sub ($c) {
875
876           # Prevent double form submission with redirect
877           my $value = $c->param('whatever');
878           $c->flash(confirmation => "We did nothing with your value ($value).");
879           $c->redirect_to('form');
880         };
881
882         app->start;
883         __DATA__
884
885         @@ form.html.ep
886         <!DOCTYPE html>
887         <html>
888           <body>
889             % if (my $confirmation = flash 'confirmation') {
890               <p><%= $confirmation %></p>
891             % }
892             %= form_for nothing => begin
893               %= text_field whatever => 'I ♥ Mojolicious!'
894               %= submit_button
895             % end
896           </body>
897         </html>
898
899       The helpers "flash" in Mojolicious::Plugin::DefaultHelpers and
900       "redirect_to" in Mojolicious::Plugin::DefaultHelpers are often used
901       together to prevent double form submission, allowing users to receive a
902       confirmation message that will vanish if they decide to reload the page
903       they've been redirected to.
904
905   Form validation
906       You can use "validation" in Mojolicious::Plugin::DefaultHelpers to
907       validate "GET" and "POST" parameters submitted to your application. All
908       unknown fields will be ignored by default, so you have to decide which
909       should be required or optional before you can perform checks on their
910       values. Every check is performed right away, so you can use the results
911       immediately to build more advanced validation logic with methods like
912       "is_valid" in Mojolicious::Validator::Validation.
913
914         use Mojolicious::Lite -signatures;
915
916         get '/' => sub ($c) {
917
918           # Check if parameters have been submitted
919           my $v = $c->validation;
920           return $c->render('index') unless $v->has_data;
921
922           # Validate parameters ("pass_again" depends on "pass")
923           $v->required('user')->size(1, 20)->like(qr/^[a-z0-9]+$/);
924           $v->required('pass_again')->equal_to('pass') if $v->optional('pass')->size(7, 500)->is_valid;
925
926           # Check if validation failed
927           return $c->render('index') if $v->has_error;
928
929           # Render confirmation
930           $c->render('thanks');
931         };
932
933         app->start;
934         __DATA__
935
936         @@ index.html.ep
937         <!DOCTYPE html>
938         <html>
939           <head>
940             <style>
941               label.field-with-error { color: #dd7e5e }
942               input.field-with-error { background-color: #fd9e7e }
943             </style>
944           </head>
945           <body>
946             %= form_for index => begin
947               %= label_for user => 'Username (required, 1-20 characters, a-z/0-9)'
948               <br>
949               %= text_field 'user', id => 'user'
950               %= submit_button
951               <br>
952               %= label_for pass => 'Password (optional, 7-500 characters)'
953               <br>
954               %= password_field 'pass', id => 'pass'
955               <br>
956               %= label_for pass_again => 'Password again (equal to the value above)'
957               <br>
958               %= password_field 'pass_again', id => 'pass_again'
959             % end
960           </body>
961         </html>
962
963         @@ thanks.html.ep
964         <!DOCTYPE html>
965         <html><body>Thank you <%= validation->param('user') %>.</body></html>
966
967       Form elements generated with tag helpers from
968       Mojolicious::Plugin::TagHelpers will automatically remember their
969       previous values and add the class "field-with-error" for fields that
970       failed validation to make styling with CSS easier.
971
972         <label class="field-with-error" for="user">
973           Username (required, only characters e-t)
974         </label>
975         <input class="field-with-error" type="text" name="user" value="sri">
976
977       For a full list of available checks see also "CHECKS" in
978       Mojolicious::Validator.
979
980   Adding form validation checks
981       Validation checks can be registered with "add_check" in
982       Mojolicious::Validator and return a false value if they were
983       successful. A true value may be used to pass along additional
984       information which can then be retrieved with "error" in
985       Mojolicious::Validator::Validation.
986
987         use Mojolicious::Lite -signatures;
988
989         # Add "range" check
990         app->validator->add_check(range => sub ($v, $name, $value, $min, $max) {
991           return $value < $min || $value > $max;
992         });
993
994         get '/' => 'form';
995
996         post '/test' => sub ($c) {
997
998           # Validate parameters with custom check
999           my $v = $c->validation;
1000           $v->required('number')->range(3, 23);
1001
1002           # Render form again if validation failed
1003           return $c->render('form') if $v->has_error;
1004
1005           # Prevent double form submission with redirect
1006           $c->flash(number => $v->param('number'));
1007           $c->redirect_to('form');
1008         };
1009
1010         app->start;
1011         __DATA__
1012
1013         @@ form.html.ep
1014         <!DOCTYPE html>
1015         <html>
1016           <body>
1017             % if (my $number = flash 'number') {
1018               <p>Thanks, the number <%= $number %> was valid.</p>
1019             % }
1020             %= form_for test => begin
1021               % if (my $err = validation->error('number')) {
1022                 <p>
1023                   %= 'Value is required.' if $err->[0] eq 'required'
1024                   %= 'Value needs to be between 3 and 23.' if $err->[0] eq 'range'
1025                 </p>
1026               % }
1027               %= text_field 'number'
1028               %= submit_button
1029             % end
1030           </body>
1031         </html>
1032
1033   Cross-site request forgery
1034       CSRF is a very common attack on web applications that trick your logged
1035       in users to submit forms they did not intend to send, with something as
1036       mundane as a link. All you have to do, to protect your users from this,
1037       is to add an additional hidden field to your forms with "csrf_field" in
1038       Mojolicious::Plugin::TagHelpers, and validate it with "csrf_protect" in
1039       Mojolicious::Validator::Validation.
1040
1041         use Mojolicious::Lite -signatures;
1042
1043         get '/' => {template => 'target'};
1044
1045         post '/' => sub ($c) {
1046
1047           # Check CSRF token
1048           my $v = $c->validation;
1049           return $c->render(text => 'Bad CSRF token!', status => 403) if $v->csrf_protect->has_error('csrf_token');
1050
1051           my $city = $v->required('city')->param('city');
1052           $c->render(text => "Low orbit ion cannon pointed at $city!") unless $v->has_error;
1053         } => 'target';
1054
1055         app->start;
1056         __DATA__
1057
1058         @@ target.html.ep
1059         <!DOCTYPE html>
1060         <html>
1061           <body>
1062             %= form_for target => begin
1063               %= csrf_field
1064               %= label_for city => 'Which city to point low orbit ion cannon at?'
1065               %= text_field 'city', id => 'city'
1066               %= submit_button
1067             %= end
1068           </body>
1069         </html>
1070
1071       For Ajax requests and the like, you can also generate a token directly
1072       with the helper "csrf_token" in Mojolicious::Plugin::DefaultHelpers,
1073       and then pass it along with the "X-CSRF-Token" request header.
1074

ADVANCED

1076       Less commonly used and more powerful features.
1077
1078   Template inheritance
1079       Inheritance takes the layout concept above one step further, the
1080       helpers "content" in Mojolicious::Plugin::DefaultHelpers and "extends"
1081       in Mojolicious::Plugin::DefaultHelpers allow you to build skeleton
1082       templates with named blocks that child templates can override.
1083
1084         use Mojolicious::Lite;
1085
1086         # first > mylayout
1087         get '/first' => {template => 'first', layout => 'mylayout'};
1088
1089         # third > second > first > mylayout
1090         get '/third' => {template => 'third', layout => 'mylayout'};
1091
1092         app->start;
1093         __DATA__
1094
1095         @@ layouts/mylayout.html.ep
1096         <!DOCTYPE html>
1097         <html>
1098           <head><title>Hello</title></head>
1099           <body><%= content %></body>
1100         </html>
1101
1102         @@ first.html.ep
1103         %= content header => begin
1104           Default header
1105         % end
1106         <div>Hello World!</div>
1107         %= content footer => begin
1108           Default footer
1109         % end
1110
1111         @@ second.html.ep
1112         % extends 'first';
1113         % content header => begin
1114           New header
1115         % end
1116
1117         @@ third.html.ep
1118         % extends 'second';
1119         % content footer => begin
1120           New footer
1121         % end
1122
1123       This chain could go on and on to allow a very high level of template
1124       reuse.
1125
1126   Custom responses
1127       Most response content, static as well as dynamic, gets served through
1128       Mojo::Asset::File and Mojo::Asset::Memory objects. For somewhat static
1129       content, like cached JSON data or temporary files, you can create your
1130       own and use the helper "reply->asset" in
1131       Mojolicious::Plugin::DefaultHelpers to serve them while allowing
1132       content negotiation to be performed with "Range", "If-Modified-Since"
1133       and "If-None-Match" headers.
1134
1135         use Mojolicious::Lite -signatures;
1136         use Mojo::Asset::File;
1137
1138         get '/leak' => sub ($c) {
1139           $c->res->headers->content_type('text/plain');
1140           $c->reply->asset(Mojo::Asset::File->new(path => '/etc/passwd'));
1141         };
1142
1143         app->start;
1144
1145       For even more control you can also just skip the helper and use
1146       "rendered" in Mojolicious::Controller to tell the renderer when you're
1147       done generating a response.
1148
1149         use Mojolicious::Lite -signatures;
1150         use Mojo::Asset::File;
1151
1152         get '/leak' => sub ($c) {
1153           $c->res->headers->content_type('text/plain');
1154           $c->res->content->asset(Mojo::Asset::File->new(path => '/etc/passwd'));
1155           $c->rendered(200);
1156         };
1157
1158         app->start;
1159
1160   Helper plugins
1161       Some helpers might be useful enough for you to share them between
1162       multiple applications, plugins make that very simple.
1163
1164         package Mojolicious::Plugin::DebugHelper;
1165         use Mojo::Base 'Mojolicious::Plugin', -signatures;
1166
1167         sub register ($self, $app, $conf) {
1168           $app->helper(debug => sub ($c, $str) {
1169             $c->app->log->debug($str);
1170           });
1171         }
1172
1173         1;
1174
1175       The "register" method will be called when you load the plugin. And to
1176       add your helper to the application, you can use "helper" in
1177       Mojolicious.
1178
1179         use Mojolicious::Lite -signatures;
1180
1181         plugin 'DebugHelper';
1182
1183         get '/' => sub ($c) {
1184           $c->debug('It works!');
1185           $c->render(text => 'Hello!');
1186         };
1187
1188         app->start;
1189
1190       A skeleton for a full CPAN compatible plugin distribution can be
1191       automatically generated.
1192
1193         $ mojo generate plugin DebugHelper
1194
1195       And if you have a "PAUSE" account (which can be requested at
1196       <http://pause.perl.org>), you are only a few commands away from
1197       releasing it to CPAN.
1198
1199         $ perl Makefile.PL
1200         $ make test
1201         $ make manifest
1202         $ make dist
1203         $ mojo cpanify -u USER -p PASS Mojolicious-Plugin-DebugHelper-0.01.tar.gz
1204
1205   Bundling assets with plugins
1206       Assets such as templates and static files can be easily bundled with
1207       your plugins, even if you plan to release them to CPAN.
1208
1209         $ mojo generate plugin AlertAssets
1210         $ mkdir Mojolicious-Plugin-AlertAssets/lib/Mojolicious/Plugin/AlertAssets
1211         $ cd Mojolicious-Plugin-AlertAssets/lib/Mojolicious/Plugin/AlertAssets
1212         $ mkdir public
1213         $ echo 'alert("Hello World!");' > public/alertassets.js
1214         $ mkdir templates
1215         $ echo '%= javascript "/alertassets.js"' > templates/alertassets.html.ep
1216
1217       Just give them reasonably unique names, ideally based on the name of
1218       your plugin, and append their respective directories to the list of
1219       search paths when "register" is called.
1220
1221         package Mojolicious::Plugin::AlertAssets;
1222         use Mojo::Base 'Mojolicious::Plugin', -signatures;
1223
1224         use Mojo::File qw(curfile);
1225
1226         sub register ($self, $app, $conf) {
1227
1228           # Append "templates" and "public" directories
1229           my $base = curfile->sibling('AlertAssets');
1230           push @{$app->renderer->paths}, $base->child('templates')->to_string;
1231           push @{$app->static->paths},   $base->child('public')->to_string;
1232         }
1233
1234         1;
1235
1236       Both will work just like normal "templates" and "public" directories
1237       once you've installed and loaded the plugin, with slightly lower
1238       precedence.
1239
1240         use Mojolicious::Lite;
1241
1242         plugin 'AlertAssets';
1243
1244         get '/alert_me';
1245
1246         app->start;
1247         __DATA__
1248
1249         @@ alert_me.html.ep
1250         <!DOCTYPE html>
1251         <html>
1252           <head>
1253             <title>Alert me!</title>
1254             %= include 'alertassets'
1255           </head>
1256           <body>You've been alerted.</body>
1257         </html>
1258
1259       And it works just the same for assets bundled in the "DATA" section of
1260       your plugin.
1261
1262         package Mojolicious::Plugin::AlertAssets;
1263         use Mojo::Base 'Mojolicious::Plugin', -signatures;
1264
1265         sub register ($self, $app, $conf) {
1266
1267           # Append class
1268           push @{$app->renderer->classes}, __PACKAGE__;
1269           push @{$app->static->classes},   __PACKAGE__;
1270         }
1271
1272         1;
1273         __DATA__
1274
1275         @@ alertassets.js
1276         alert("Hello World!");
1277
1278         @@ alertassets.html.ep
1279         %= javascript "/alertassets.js"
1280
1281   Post-processing dynamic content
1282       While post-processing tasks are generally very easy with the hook
1283       "after_dispatch" in Mojolicious, for content generated by the renderer
1284       it is a lot more efficient to use "after_render" in Mojolicious.
1285
1286         use Mojolicious::Lite -signatures;
1287         use IO::Compress::Gzip qw(gzip);
1288
1289         hook after_render => sub ($c, $output, $format) {
1290
1291           # Check if "gzip => 1" has been set in the stash
1292           return unless $c->stash->{gzip};
1293
1294           # Check if user agent accepts gzip compression
1295           return unless ($c->req->headers->accept_encoding // '') =~ /gzip/i;
1296           $c->res->headers->append(Vary => 'Accept-Encoding');
1297
1298           # Compress content with gzip
1299           $c->res->headers->content_encoding('gzip');
1300           gzip $output, \my $compressed;
1301           $$output = $compressed;
1302         };
1303
1304         get '/' => {template => 'hello', title => 'Hello', gzip => 1};
1305
1306         app->start;
1307         __DATA__
1308
1309         @@ hello.html.ep
1310         <!DOCTYPE html>
1311         <html>
1312           <head><title><%= title %></title></head>
1313           <body>Compressed content.</body>
1314         </html>
1315
1316       If you want to compress all dynamically generated content you can also
1317       activate "compress" in Mojolicious::Renderer.
1318
1319   Streaming
1320       You don't have to render all content at once, the method "write" in
1321       Mojolicious::Controller can also be used to stream a series of smaller
1322       chunks.
1323
1324         use Mojolicious::Lite -signatures;
1325
1326         get '/' => sub ($c) {
1327
1328           # Prepare body
1329           my $body = 'Hello World!';
1330           $c->res->headers->content_length(length $body);
1331
1332           # Start writing directly with a drain callback
1333           my $drain = sub ($c) {
1334             my $chunk = substr $body, 0, 1, '';
1335             $c->write($chunk, length $body ? __SUB__ : undef);
1336           };
1337           $c->$drain;
1338         };
1339
1340         app->start;
1341
1342       The drain callback will be executed whenever the entire previous chunk
1343       of data has actually been written.
1344
1345         HTTP/1.1 200 OK
1346         Date: Sat, 13 Sep 2014 16:48:29 GMT
1347         Content-Length: 12
1348         Server: Mojolicious (Perl)
1349
1350         Hello World!
1351
1352       Instead of providing a "Content-Length" header you can also call
1353       "finish" in Mojolicious::Controller and close the connection manually
1354       once you are done.
1355
1356         use Mojolicious::Lite -signatures;
1357
1358         get '/' => sub ($c) {
1359
1360           # Prepare body
1361           my $body = 'Hello World!';
1362
1363           # Start writing directly with a drain callback
1364           my $drain = sub ($c) {
1365             my $chunk = substr $body, 0, 1, '';
1366             length $chunk ? $c->write($chunk, __SUB__) : $c->finish;
1367           };
1368           $c->$drain;
1369         };
1370
1371         app->start;
1372
1373       While this is rather inefficient, as it prevents keep-alive, it is
1374       sometimes necessary for EventSource and similar applications.
1375
1376         HTTP/1.1 200 OK
1377         Date: Sat, 13 Sep 2014 16:48:29 GMT
1378         Connection: close
1379         Server: Mojolicious (Perl)
1380
1381         Hello World!
1382
1383   Chunked transfer encoding
1384       For very dynamic content you might not know the response content length
1385       in advance, that's where the chunked transfer encoding and
1386       "write_chunk" in Mojolicious::Controller come in handy. A common use
1387       would be to send the "head" section of an HTML document to the browser
1388       in advance and speed up preloading of referenced images and
1389       stylesheets.
1390
1391         use Mojolicious::Lite -signatures;
1392
1393         get '/' => sub ($c) {
1394           $c->write_chunk('<html><head><title>Example</title></head>' => sub ($c) {
1395             $c->finish('<body>Example</body></html>');
1396           });
1397         };
1398
1399         app->start;
1400
1401       The optional drain callback ensures that all previous chunks have been
1402       written before processing continues. To end the stream you can call
1403       "finish" in Mojolicious::Controller or write an empty chunk of data.
1404
1405         HTTP/1.1 200 OK
1406         Date: Sat, 13 Sep 2014 16:48:29 GMT
1407         Transfer-Encoding: chunked
1408         Server: Mojolicious (Perl)
1409
1410         29
1411         <html><head><title>Example</title></head>
1412         1b
1413         <body>Example</body></html>
1414         0
1415
1416       Especially in combination with long inactivity timeouts this can be
1417       very useful for Comet (long polling). Due to limitations in some web
1418       servers this might not work perfectly in all deployment environments.
1419
1420   Encoding
1421       Templates stored in files are expected to be "UTF-8" by default, but
1422       that can be easily changed with "encoding" in Mojolicious::Renderer.
1423
1424         $app->renderer->encoding('koi8-r');
1425
1426       All templates from the "DATA" section are bound to the encoding of the
1427       Perl script.
1428
1429         use Mojolicious::Lite;
1430
1431         get '/heart';
1432
1433         app->start;
1434         __DATA__
1435
1436         @@ heart.html.ep
1437         I ♥ Mojolicious!
1438
1439   Base64 encoded DATA files
1440       Base64 encoded static files such as images can be easily stored in the
1441       "DATA" section of your application, similar to templates.
1442
1443         use Mojolicious::Lite;
1444
1445         get '/' => {text => 'I ♥ Mojolicious!'};
1446
1447         app->start;
1448         __DATA__
1449
1450         @@ favicon.ico (base64)
1451         ...base64 encoded image...
1452
1453   Inflating DATA templates
1454       Templates stored in files get preferred over files from the "DATA"
1455       section, this allows you to include a default set of templates in your
1456       application that the user can later customize. The command
1457       Mojolicious::Command::Author::inflate will write all templates and
1458       static files from the "DATA" section into actual files in the
1459       "templates" and "public" directories.
1460
1461         $ ./myapp.pl inflate
1462
1463   Customizing the template syntax
1464       You can easily change the whole template syntax by loading
1465       Mojolicious::Plugin::EPRenderer with a custom configuration.
1466
1467         use Mojolicious::Lite;
1468
1469         plugin EPRenderer => {
1470           name     => 'mustache',
1471           template => {
1472             tag_start => '{{',
1473             tag_end   => '}}'
1474           }
1475         };
1476
1477         get '/:name' => {name => 'Anonymous'} => 'index';
1478
1479         app->start;
1480         __DATA__
1481
1482         @@ index.html.mustache
1483         Hello {{= $name }}.
1484
1485       Mojo::Template contains the whole list of available options.
1486
1487   Adding your favorite template system
1488       Maybe you would prefer a different template system than "ep", which is
1489       provided by Mojolicious::Plugin::EPRenderer, and there is not already a
1490       plugin on CPAN for your favorite one. All you have to do, is to add a
1491       new "handler" with "add_handler" in Mojolicious::Renderer when
1492       "register" is called.
1493
1494         package Mojolicious::Plugin::MyRenderer;
1495         use Mojo::Base 'Mojolicious::Plugin', -signatures;
1496
1497         sub register ($self, $app, $conf) {
1498
1499           # Add "mine" handler
1500           $app->renderer->add_handler(mine => sub ($renderer, $c, $output, $options) {
1501
1502             # Check for one-time use inline template
1503             my $inline_template = $options->{inline};
1504
1505             # Check for appropriate template in "templates" directories
1506             my $template_path = $renderer->template_path($options);
1507
1508             # Check for appropriate template in DATA sections
1509             my $data_template = $renderer->get_data_template($options);
1510
1511             # This part is up to you and your template system :)
1512             ...
1513
1514             # Pass the rendered result back to the renderer
1515             $$output = 'Hello World!';
1516
1517             # Or just die if an error occurs
1518             die 'Something went wrong with the template';
1519           });
1520         }
1521
1522         1;
1523
1524       An "inline" template, if provided by the user, will be passed along
1525       with the options. You can use "template_path" in Mojolicious::Renderer
1526       to search the "templates" directories of the application, and
1527       "get_data_template" in Mojolicious::Renderer to search the "DATA"
1528       sections.
1529
1530         use Mojolicious::Lite;
1531
1532         plugin 'MyRenderer';
1533
1534         # Render an inline template
1535         get '/inline' => {inline => '...', handler => 'mine'};
1536
1537         # Render a template from the DATA section
1538         get '/data' => {template => 'test'};
1539
1540         app->start;
1541         __DATA__
1542
1543         @@ test.html.mine
1544         ...
1545
1546   Adding a handler to generate binary data
1547       By default the renderer assumes that every "handler" generates
1548       characters that need to be automatically encoded, but this can be
1549       easily disabled if you're generating bytes instead.
1550
1551         use Mojolicious::Lite -signatures;
1552         use Storable qw(nfreeze);
1553
1554         # Add "storable" handler
1555         app->renderer->add_handler(storable => sub ($renderer, $c, $output, $options) {
1556
1557           # Disable automatic encoding
1558           delete $options->{encoding};
1559
1560           # Encode data from stash value
1561           $$output = nfreeze delete $c->stash->{storable};
1562         });
1563
1564         # Set "handler" value automatically if "storable" value is set already
1565         app->hook(before_render => sub ($c, $args) {
1566           $args->{handler} = 'storable' if exists $args->{storable} || exists $c->stash->{storable};
1567         });
1568
1569         get '/' => {storable => {i => '♥ mojolicious'}};
1570
1571         app->start;
1572
1573       The hook "before_render" in Mojolicious can be used to make stash
1574       values like "storable" special, so that they no longer require a
1575       "handler" value to be set explicitly.
1576
1577         # Explicit "handler" value
1578         $c->render(storable => {i => '♥ mojolicious'}, handler => 'storable');
1579
1580         # Implicit "handler" value (with "before_render" hook)
1581         $c->render(storable => {i => '♥ mojolicious'});
1582

MORE

1584       You can continue with Mojolicious::Guides now or take a look at the
1585       Mojolicious wiki <https://github.com/mojolicious/mojo/wiki>, which
1586       contains a lot more documentation and examples by many different
1587       authors.
1588

SUPPORT

1590       If you have any questions the documentation might not yet answer, don't
1591       hesitate to ask in the Forum <https://forum.mojolicious.org>, on Matrix
1592       <https://matrix.to/#/#mojo:matrix.org>, or IRC
1593       <https://web.libera.chat/#mojo>.
1594
1595
1596
1597perl v5.36.0                      2023-01-20 Mojolicious::Guides::Rendering(3)
Impressum