File Coverage

blib/lib/Mojolicious/Controller.pm
Criterion Covered Total %
statement 191 213 89.6
branch 99 110 90.0
condition 35 55 63.6
subroutine 114 116 98.2
pod 28 29 96.5
total 467 523 89.2


line stmt bran cond sub pod time code
1             package Mojolicious::Controller;
2 55     55   123766 use Mojo::Base -base;
  55         140  
  55         501  
3              
4             # No imports, for security reasons!
5 55     55   424 use Carp ();
  55         134  
  55         1028  
6 55     55   2201 use Digest::SHA ();
  55         7667  
  55         1188  
7 55     55   1318 use Mojo::ByteStream;
  55         120  
  55         3387  
8 55     55   1741 use Mojo::DynamicMethods -dispatch;
  55         122  
  55         535  
9 55     55   1473 use Mojo::URL;
  55         153  
  55         495  
10 55     55   434 use Mojo::Util;
  55         135  
  55         2714  
11 55     55   36407 use Mojolicious::Routes::Match;
  55         234  
  55         421  
12 55     55   520 use Scalar::Util ();
  55         139  
  55         298122  
13              
14             my $ABSOLUTE = qr!^(?:[^:/?#]+:|//|#)!;
15              
16             has [qw(app tx)] => undef, weak => 1;
17             has match => sub { Mojolicious::Routes::Match->new(root => shift->app->routes) };
18              
19             sub BUILD_DYNAMIC {
20 3661     3661 0 7833 my ($class, $method, $dyn_methods) = @_;
21              
22             return sub {
23 512     512   4068 my $self = shift;
        512      
        512      
        512      
        512      
        512      
        512      
        512      
        512      
        512      
        512      
        512      
        512      
        512      
        512      
        512      
        512      
        512      
        512      
        568      
        512      
        512      
        512      
        512      
        512      
        512      
        512      
        512      
        512      
        512      
        512      
        512      
        512      
        512      
        512      
        512      
        512      
        512      
        512      
        512      
        512      
        512      
        512      
        512      
        512      
        512      
        512      
        512      
        529      
        512      
        512      
        512      
        512      
        512      
        512      
        512      
        512      
        512      
        568      
        568      
        568      
        568      
        512      
        512      
        536      
        512      
        512      
        512      
        512      
        512      
        512      
        159      
24 512         5157 my $dynamic = $dyn_methods->{$self->{app}{renderer}}{$method};
25 512 50       2852 return $self->$dynamic(@_) if $dynamic;
26 0         0 my $package = ref $self;
27 0         0 Carp::croak qq{Can't locate object method "$method" via package "$package"};
28 3661         24237 };
29             }
30              
31 1     1 1 9 sub continue { $_[0]->app->routes->continue($_[0]) }
32              
33             sub cookie {
34 154     154 1 791 my ($self, $name) = (shift, shift);
35              
36             # Response cookie
37 154 100       380 if (@_) {
38              
39             # Cookie too big
40 120   100     219 my $cookie = {name => $name, value => shift, %{shift // {}}};
  120         820  
41 120 50       450 $self->helpers->log->error(qq{Cookie "$name" is bigger than 4KiB}) if length $cookie->{value} > 4096;
42              
43 120         332 $self->res->cookies($cookie);
44 120         592 return $self;
45             }
46              
47             # Request cookies
48 34 100       83 return undef unless my $cookie = $self->req->cookie($name);
49 21         66 return $cookie->value;
50             }
51              
52             sub encrypted_cookie {
53 0     0 1 0 my ($self, $name, $value, $options) = @_;
54              
55             # Request cookie
56 0 0       0 return $self->every_encrypted_cookie($name)->[-1] unless defined $value;
57              
58             # Response cookie
59 0         0 my $app = $self->app;
60 0         0 my $secret = $app->secrets->[0];
61 0         0 my $moniker = $app->moniker;
62 0         0 return $self->cookie($name, Mojo::Util::encrypt_cookie($value, $secret, $moniker), $options);
63             }
64              
65 261     261 1 481 sub every_cookie { [map { $_->value } @{shift->req->every_cookie(shift)}] }
  78         254  
  261         766  
66              
67             sub every_encrypted_cookie {
68 0     0 1 0 my ($self, $name) = @_;
69              
70 0         0 my $app = $self->app;
71 0         0 my $secrets = $app->secrets;
72 0         0 my $moniker = $app->moniker;
73 0         0 my @results;
74 0         0 for my $value (@{$self->every_cookie($name)}) {
  0         0  
75 0         0 my $decrypted;
76 0         0 for my $secret (@$secrets) {
77 0 0       0 last if defined($decrypted = Mojo::Util::decrypt_cookie($value, $secret, $moniker));
78             }
79 0 0       0 if (defined $decrypted) { push @results, $decrypted }
  0         0  
80              
81 0         0 else { $self->helpers->log->trace(qq{Cookie "$name" is not encrypted}) }
82             }
83              
84 0         0 return \@results;
85             }
86              
87             sub every_param {
88 391     391 1 961 my ($self, $name) = @_;
89              
90             # Captured unreserved values
91 391   100     1089 my $captures = $self->stash->{'mojo.captures'} //= {};
92 391 100 100     1616 if (exists $captures->{$name} && !$self->app->routes->is_reserved($name)) {
93 84         182 my $value = $captures->{$name};
94 84 100       758 return ref $value eq 'ARRAY' ? $value : [$value];
95             }
96              
97             # Uploads or param values
98 307         924 my $req = $self->req;
99 307         1646 my $uploads = $req->every_upload($name);
100 307 100       1555 return @$uploads ? $uploads : $req->every_param($name);
101             }
102              
103             sub every_signed_cookie {
104 259     259 1 663 my ($self, $name) = @_;
105              
106 259         724 my $secrets = $self->app->secrets;
107 259         526 my @results;
108 259         448 for my $value (@{$self->every_cookie($name)}) {
  259         970  
109              
110             # Check signature with rotating secrets
111 76 100       808 if ($value =~ s/--([^\-]+)$//) {
112 67         215 my $signature = $1;
113              
114 67         181 my $valid;
115 67         162 for my $secret (@$secrets) {
116 76         1116 my $check = Digest::SHA::hmac_sha256_hex("$name=$value", $secret);
117 76 100 50     360 ++$valid and last if Mojo::Util::secure_compare($signature, $check);
118             }
119 67 100       186 if ($valid) { push @results, $value }
  55         206  
120              
121 12         41 else { $self->helpers->log->trace(qq{Cookie "$name" has bad signature}) }
122             }
123              
124 9         24 else { $self->helpers->log->trace(qq{Cookie "$name" is not signed}) }
125             }
126              
127 259         1607 return \@results;
128             }
129              
130             sub finish {
131 35     35 1 221 my $self = shift;
132              
133             # WebSocket
134 35   33     160 my $tx = $self->tx || Carp::croak 'Transaction already destroyed';
135 35 100 50     158 $tx->finish(@_) and return $tx->established ? $self : $self->rendered(101) if $tx->is_websocket;
    100          
136              
137             # Chunked stream
138 26 100       91 return @_ ? $self->write_chunk(@_)->write_chunk('') : $self->write_chunk('') if $tx->res->content->is_chunked;
    100          
139              
140             # Normal stream
141 20 100       132 return @_ ? $self->write(@_)->write('') : $self->write('');
142             }
143              
144 4941     4941 1 20983 sub helpers { $_[0]->app->renderer->get_helper('')->($_[0]) }
145              
146             sub on {
147 93     93 1 699 my ($self, $name, $cb) = @_;
148 93   33     351 my $tx = $self->tx || Carp::croak 'Transaction already destroyed';
149 93 100 66     393 $self->rendered(101) if $tx->is_websocket && !$tx->established;
150 93     89   673 return $tx->on($name => sub { shift; $self->$cb(@_) });
  89         207  
  89         439  
151             }
152              
153             sub param {
154 259     259 1 1312 my ($self, $name) = (shift, shift);
155 259 100       1102 return $self->every_param($name)->[-1] unless @_;
156 27 100       85 $self->stash->{'mojo.captures'}{$name} = @_ > 1 ? [@_] : $_[0];
157 27         72 return $self;
158             }
159              
160             sub render {
161 1006     1006 1 3371 my $self = shift;
162              
163             # Template may be first argument
164 1006 100       7548 my ($template, $args) = (@_ % 2 ? shift : undef, {@_});
165 1006 100       3523 $args->{template} = $template if $template;
166 1006         5318 my $app = $self->app;
167 1006         3495 my $plugins = $app->plugins->emit_hook(before_render => $self, $args);
168              
169             # Localize "extends" and "layout" to allow argument overrides
170 1006         2482 my ($maybe, $ts) = @{$args}{'mojo.maybe', 'mojo.string'};
  1006         3082  
171 1006         2977 my $stash = $self->stash;
172 1006 100       3600 local $stash->{layout} = $stash->{layout} if exists $stash->{layout};
173 1006 100       3185 local $stash->{extends} = $stash->{extends} if exists $stash->{extends};
174              
175             # Rendering to string
176 1006 100 100     5738 local @{$stash}{keys %$args} if $ts || $maybe;
  577         4663  
177 1006 100       2840 delete @{$stash}{qw(layout extends)} if $ts;
  26         72  
178              
179             # All other arguments just become part of the stash
180 1006         4581 @$stash{keys %$args} = values %$args;
181 1006         3428 my $renderer = $app->renderer;
182 1006         4871 my ($output, $format) = $renderer->render($self);
183              
184             # Maybe no 404
185 986 50       3431 return defined $output ? Mojo::ByteStream->new($output) : undef if $ts;
    100          
186 961 100       8220 return $maybe ? undef : Carp::croak("Could not render a response") unless defined $output;
    100          
187              
188 770         5119 $plugins->emit_hook(after_render => $self, \$output, $format);
189 770         5053 return $renderer->respond($self, $output, $format, $stash->{status});
190             }
191              
192 1034     1034 1 3186 sub render_later { shift->stash('mojo.rendered' => 1) }
193              
194 556     556 1 3119 sub render_maybe { shift->render(@_, 'mojo.maybe' => 1) }
195              
196 26     26 1 226 sub render_to_string { shift->render(@_, 'mojo.string' => 1) }
197              
198             sub rendered {
199 1165     1165 1 3356 my ($self, $status) = @_;
200              
201             # Make sure we have a status
202 1165 100       3869 $self->res->code($status) if $status;
203              
204             # Finish transaction
205 1165         4527 my $stash = $self->stash;
206 1165 100 66     8587 if (!$stash->{'mojo.finished'} && ++$stash->{'mojo.finished'}) {
207 1010         3144 my $res = $self->res;
208 1010 100 100     5175 $res->code(200) if !$status && !$res->code;
209              
210             # Disable auto rendering and stop timer
211 1010         3955 my $app = $self->render_later->app;
212             $self->helpers->log->trace(sub {
213 276     276   3949 my $timing = $self->helpers->timing;
214 276   50     1373 my $elapsed = $timing->elapsed('mojo.timer') // 0;
215 276   50     6277 my $rps = $timing->rps($elapsed) // '??';
216 276         1136 my $code = $res->code;
217 276   33     1122 my $msg = $res->message || $res->default_message($code);
218 276         2671 return "$code $msg (${elapsed}s, $rps/s)";
219 1010 100       5615 }) unless $stash->{'mojo.static'};
220              
221 1010         10528 $app->plugins->emit_hook_reverse(after_dispatch => $self);
222 1010         4210 $app->sessions->store($self);
223             }
224 1165         3819 $self->tx->resume;
225 1165         13195 return $self;
226             }
227              
228 5875   33 5875 1 22040 sub req { (shift->tx || Carp::croak 'Transaction already destroyed')->req }
229 3677   33 3677 1 11684 sub res { (shift->tx || Carp::croak 'Transaction already destroyed')->res }
230              
231             sub send {
232 105     105 1 1074 my ($self, $msg, $cb) = @_;
233 105   33     455 my $tx = $self->tx || Carp::croak 'Transaction already destroyed';
234 105 100       423 Carp::croak 'No WebSocket connection to send message to' unless $tx->is_websocket;
235 104 100   2   634 $tx->send($msg, $cb ? sub { shift; $self->$cb(@_) } : ());
  2         6  
  2         17  
236 104 100       407 return $tx->established ? $self : $self->rendered(101);
237             }
238              
239             sub session {
240 253     253 1 821 my $self = shift;
241              
242 253         733 my $stash = $self->stash;
243 253 100       1168 $self->app->sessions->load($self) unless exists $stash->{'mojo.active_session'};
244              
245             # Hash
246 253   100     1221 my $session = $stash->{'mojo.session'} //= {};
247 253 100       1151 return $session unless @_;
248              
249             # Get
250 41 100 66     295 return $session->{$_[0]} unless @_ > 1 || ref $_[0];
251              
252             # Set
253 23 50       96 my $values = ref $_[0] ? $_[0] : {@_};
254 23         93 @$session{keys %$values} = values %$values;
255              
256 23         91 return $self;
257             }
258              
259             sub signed_cookie {
260 331     331 1 1255 my ($self, $name, $value, $options) = @_;
261              
262             # Request cookie
263 331 100       1322 return $self->every_signed_cookie($name)->[-1] unless defined $value;
264              
265             # Response cookie
266 74         329 my $sum = Digest::SHA::hmac_sha256_hex("$name=$value", $self->app->secrets->[0]);
267 74         405 return $self->cookie($name, "$value--$sum", $options);
268             }
269              
270 20942     20942 1 65954 sub stash { Mojo::Util::_stash(stash => @_) }
271              
272             sub url_for {
273 656   100 656 1 3225 my ($self, $target) = (shift, shift // '');
274              
275             # Absolute URL
276 656 100 66     2482 return $target if Scalar::Util::blessed $target && $target->isa('Mojo::URL');
277 636 100       4996 return Mojo::URL->new($target) if $target =~ $ABSOLUTE;
278              
279             # Base
280 615         3213 my $url = Mojo::URL->new;
281 615         2117 my $req = $self->req;
282 615         3100 my $base = $url->base($req->url->base->clone)->base->userinfo(undef);
283              
284             # Relative URL
285 615         2165 my $path = $url->path;
286 615 100       2389 if ($target =~ m!^/!) {
287 451 100       3455 if (defined(my $prefix = $self->stash->{path})) {
288 30         107 my $real = $req->url->path->to_route;
289 30         831 $real =~ s!/?\Q$prefix\E$!$target!;
290 30         107 $target = $real;
291             }
292 451         1609 $url->parse($target);
293             }
294              
295             # Route
296             else {
297 164         612 my $generated = $self->match->path_for($target, @_);
298 164 100       1392 $path->parse($generated->{path}) if $generated->{path};
299 164 50       668 $base->scheme($base->protocol eq 'https' ? 'wss' : 'ws') if $generated->{websocket};
    100          
300             }
301              
302             # Make path absolute
303 615         1860 my $base_path = $base->path;
304 615         1207 unshift @{$path->parts}, @{$base_path->parts};
  615         1766  
  615         1922  
305 615         1916 $base_path->parts([])->trailing_slash(0);
306              
307 615         3831 return $url;
308             }
309              
310             sub url_for_asset {
311 21     21 1 70 my ($self, $asset) = @_;
312 21 100       341 return $self->url_for($asset =~ $ABSOLUTE ? $asset : $self->app->static->asset_path($asset));
313             }
314              
315             sub url_for_file {
316 386     386 1 925 my ($self, $file) = @_;
317 386 100       4542 return $self->url_for($file =~ $ABSOLUTE ? $file : $self->app->static->file_path($file));
318             }
319              
320             sub write {
321 41     41 1 202 my ($self, $chunk, $cb) = @_;
322 41 100   4   129 $self->res->content->write($chunk, $cb ? sub { shift; $self->$cb(@_) } : ());
  4         7  
  4         14  
323 41         135 return $self->rendered;
324             }
325              
326             sub write_chunk {
327 61     61 1 550 my ($self, $chunk, $cb) = @_;
328 61 100   37   175 $self->res->content->write_chunk($chunk, $cb ? sub { shift; $self->$cb(@_) } : ());
  37         80  
  37         123  
329 61         190 return $self->rendered;
330             }
331              
332             sub write_sse {
333 57     57 1 882 my ($self, $event, $cb) = @_;
334 57 100   1   214 $self->res->content->write_sse($event, $cb ? sub { shift; $self->$cb(@_) } : ());
  1         3  
  1         6  
335 57         246 return $self->rendered;
336             }
337              
338             1;
339              
340             =encoding utf8
341              
342             =head1 NAME
343              
344             Mojolicious::Controller - Controller base class
345              
346             =head1 SYNOPSIS
347              
348             # Controller
349             package MyApp::Controller::Foo;
350             use Mojo::Base 'Mojolicious::Controller', -signatures;
351              
352             # Action
353             sub bar ($self) {
354             my $name = $self->param('name');
355             $self->res->headers->cache_control('max-age=1, no-cache');
356             $self->render(json => {hello => $name});
357             }
358              
359             =head1 DESCRIPTION
360              
361             L is the base class for your L controllers. It is also the default controller
362             class unless you set L.
363              
364             =head1 ATTRIBUTES
365              
366             L implements the following attributes.
367              
368             =head2 app
369              
370             my $app = $c->app;
371             $c = $c->app(Mojolicious->new);
372              
373             A reference back to the application that dispatched to this controller, usually a L object. Note that this
374             attribute is weakened.
375              
376             # Use application logger
377             $c->app->log->debug('Hello Mojo');
378              
379             # Generate path
380             my $path = $c->app->home->child('templates', 'foo', 'bar.html.ep');
381              
382             =head2 match
383              
384             my $m = $c->match;
385             $c = $c->match(Mojolicious::Routes::Match->new);
386              
387             Router results for the current request, defaults to a L object.
388              
389             # Introspect
390             my $name = $c->match->endpoint->name;
391             my $foo = $c->match->endpoint->pattern->defaults->{foo};
392             my $action = $c->match->stack->[-1]{action};
393              
394             =head2 tx
395              
396             my $tx = $c->tx;
397             $c = $c->tx(Mojo::Transaction::HTTP->new);
398              
399             The transaction that is currently being processed, usually a L or
400             L object. Note that this attribute is weakened. So the object needs to be referenced
401             elsewhere as well when you're performing non-blocking operations and the underlying connection might get closed early.
402              
403             # Check peer information
404             my $address = $c->tx->remote_address;
405             my $port = $c->tx->remote_port;
406              
407             # Increase size limit for WebSocket messages to 16MiB
408             $c->tx->max_websocket_size(16777216) if $c->tx->is_websocket;
409              
410             # Perform non-blocking operation without knowing the connection status
411             my $tx = $c->tx;
412             Mojo::IOLoop->timer(2 => sub {
413             $c->app->log->debug($tx->is_finished ? 'Finished' : 'In progress');
414             });
415              
416             =head1 METHODS
417              
418             L inherits all methods from L and implements the following new ones.
419              
420             =head2 continue
421              
422             $c->continue;
423              
424             Continue dispatch chain from an intermediate destination with L.
425              
426             =head2 cookie
427              
428             my $value = $c->cookie('foo');
429             $c = $c->cookie(foo => 'bar');
430             $c = $c->cookie(foo => 'bar', {path => '/'});
431              
432             Access request cookie values and create new response cookies. If there are multiple values sharing the same name, and
433             you want to access more than just the last one, you can use L.
434              
435             # Create response cookie with domain and expiration date
436             $c->cookie(user => 'sri', {domain => 'example.com', expires => time + 60});
437              
438             # Create secure response cookie
439             $c->cookie(secret => 'I <3 Mojolicious', {secure => 1, httponly => 1});
440              
441             =head2 encrypted_cookie
442              
443             my $value = $c->encrypted_cookie('foo');
444             $c = $c->encrypted_cookie(foo => 'bar');
445             $c = $c->encrypted_cookie(foo => 'bar', {path => '/'});
446              
447             Access encrypted request cookie values and create new encrypted response cookies. If there are multiple values sharing
448             the same name, and you want to access more than just the last one, you can use L. Cookies
449             are encrypted with ChaCha20-Poly1305, to prevent tampering, and the ones failing decryption will be automatically
450             discarded.
451              
452             =head2 every_cookie
453              
454             my $values = $c->every_cookie('foo');
455              
456             Similar to L, but returns all request cookie values sharing the same name as an array reference.
457              
458             $ Get first cookie value
459             my $first = $c->every_cookie('foo')->[0];
460              
461             =head2 every_encrypted_cookie
462              
463             my $values = $c->every_encrypted_cookie('foo');
464              
465             Similar to L, but returns all encrypted request cookie values sharing the same name as an array
466             reference.
467              
468             # Get first encrypted cookie value
469             my $first = $c->every_encrypted_cookie('foo')->[0];
470              
471             =head2 every_param
472              
473             my $values = $c->every_param('foo');
474              
475             Similar to L, but returns all values sharing the same name as an array reference.
476              
477             # Get first value
478             my $first = $c->every_param('foo')->[0];
479              
480             =head2 every_signed_cookie
481              
482             my $values = $c->every_signed_cookie('foo');
483              
484             Similar to L, but returns all signed request cookie values sharing the same name as an array
485             reference.
486              
487             # Get first signed cookie value
488             my $first = $c->every_signed_cookie('foo')->[0];
489              
490             =head2 finish
491              
492             $c = $c->finish;
493             $c = $c->finish(1000);
494             $c = $c->finish(1003 => 'Cannot accept data!');
495             $c = $c->finish('Bye!');
496              
497             Close WebSocket connection or long poll stream gracefully. This method will automatically respond to WebSocket
498             handshake requests with a C<101> response status, to establish the WebSocket connection.
499              
500             =head2 helpers
501              
502             my $helpers = $c->helpers;
503              
504             Return a proxy object containing the current controller object and on which helpers provided by L can be
505             called. This includes all helpers from L and L.
506              
507             # Make sure to use the "title" helper and not the controller method
508             $c->helpers->title('Welcome!');
509              
510             # Use a nested helper instead of the "reply" controller method
511             $c->helpers->reply->not_found;
512              
513             =head2 on
514              
515             my $cb = $c->on(finish => sub {...});
516              
517             Subscribe to events of L, which is usually a L or L
518             object. This method will automatically respond to WebSocket handshake requests with a C<101> response status, to
519             establish the WebSocket connection.
520              
521             # Do something after the transaction has been finished
522             $c->on(finish => sub ($c) {
523             $c->app->log->debug('All data has been sent');
524             });
525              
526             # Receive WebSocket message
527             $c->on(message => sub ($c, $msg) {
528             $c->app->log->debug("Message: $msg");
529             });
530              
531             # Receive JSON object via WebSocket message
532             $c->on(json => sub ($c, $hash) {
533             $c->app->log->debug("Test: $hash->{test}");
534             });
535              
536             # Receive WebSocket "Binary" message
537             $c->on(binary => sub ($c, $bytes) {
538             my $len = length $bytes;
539             $c->app->log->debug("Received $len bytes");
540             });
541              
542             =head2 param
543              
544             my $value = $c->param('foo');
545             $c = $c->param(foo => 'ba;r');
546             $c = $c->param(foo => 'ba;r', 'baz');
547             $c = $c->param(foo => ['ba;r', 'baz']);
548              
549             Access route placeholder values that are not reserved stash values, file uploads as well as C and C
550             parameters extracted from the query string and C or C message
551             body, in that order. If there are multiple values sharing the same name, and you want to access more than just the last
552             one, you can use L. Parts of the request body need to be loaded into memory to parse C
553             parameters, so you have to make sure it is not excessively large. There's a 16MiB limit for requests by default.
554              
555             # Get first value
556             my $first = $c->every_param('foo')->[0];
557              
558             For more control you can also access request information directly.
559              
560             # Only GET parameters
561             my $foo = $c->req->query_params->param('foo');
562              
563             # Only POST parameters
564             my $foo = $c->req->body_params->param('foo');
565              
566             # Only GET and POST parameters
567             my $foo = $c->req->param('foo');
568              
569             # Only file uploads
570             my $foo = $c->req->upload('foo');
571              
572             =head2 render
573              
574             my $bool = $c->render;
575             my $bool = $c->render(foo => 'bar', baz => 23);
576             my $bool = $c->render(template => 'foo/index');
577             my $bool = $c->render(template => 'index', format => 'html');
578             my $bool = $c->render(data => $bytes);
579             my $bool = $c->render(text => 'Hello!');
580             my $bool = $c->render(json => {foo => 'bar'});
581             my $bool = $c->render(handler => 'something');
582             my $bool = $c->render('foo/index');
583              
584             Render content with L and emit hooks L as well as
585             L, or dies if no response could be generated. All additional key/value pairs get merged into
586             the L.
587              
588             # Render characters
589             $c->render(text => 'I ♥ Mojolicious!');
590              
591             # Render characters (alternative)
592             $c->stash(text => 'I ♥ Mojolicious!')->render;
593              
594             # Render binary data
595             use Mojo::JSON qw(encode_json);
596             $c->render(data => encode_json({test => 'I ♥ Mojolicious!'}));
597              
598             # Render JSON
599             $c->render(json => {test => 'I ♥ Mojolicious!'});
600              
601             # Render inline template
602             $c->render(inline => '<%= 1 + 1 %>');
603              
604             # Render template "foo/bar.html.ep"
605             $c->render(template => 'foo/bar', format => 'html', handler => 'ep');
606              
607             # Render template "test.*.*" with arbitrary values "foo" and "bar"
608             $c->render(template => 'test', foo => 'test', bar => 23);
609              
610             # Render template "test.xml.*"
611             $c->render(template => 'test', format => 'xml');
612              
613             # Render template "test.xml.*" (alternative)
614             $c->render('test', format => 'xml');
615              
616             =head2 render_later
617              
618             $c = $c->render_later;
619              
620             Disable automatic rendering to delay response generation, only necessary if automatic rendering would result in a
621             response.
622              
623             # Delayed rendering
624             $c->render_later;
625             Mojo::IOLoop->timer(2 => sub { $c->render(text => 'Delayed by 2 seconds!') });
626              
627             =head2 render_maybe
628              
629             my $bool = $c->render_maybe;
630             my $bool = $c->render_maybe(foo => 'bar', baz => 23);
631             my $bool = $c->render_maybe('foo/index', format => 'html');
632              
633             Try to render content, but do not call Lnot_found"> if no response
634             could be generated, all arguments get localized automatically and are only available during this render operation,
635             takes the same arguments as L.
636              
637             # Render template "index_local" only if it exists
638             $c->render_maybe('index_local') or $c->render('index');
639              
640             =head2 render_to_string
641              
642             my $output = $c->render_to_string('foo/index', format => 'pdf');
643              
644             Try to render content and return it wrapped in a L object or return C, all arguments get
645             localized automatically and are only available during this render operation, takes the same arguments as L.
646              
647             # Render inline template
648             my $two = $c->render_to_string(inline => '<%= 1 + 1 %>');
649              
650             =head2 rendered
651              
652             $c = $c->rendered;
653             $c = $c->rendered(302);
654              
655             Finalize response and emit hook L, defaults to using a C<200> response code.
656              
657             # Custom response
658             $c->res->headers->content_type('text/plain');
659             $c->res->body('Hello World!');
660             $c->rendered(200);
661              
662             =head2 req
663              
664             my $req = $c->req;
665              
666             Get L object from L.
667              
668             # Longer version
669             my $req = $c->tx->req;
670              
671             # Extract request information
672             my $id = $c->req->request_id;
673             my $method = $c->req->method;
674             my $url = $c->req->url->to_abs;
675             my $info = $c->req->url->to_abs->userinfo;
676             my $host = $c->req->url->to_abs->host;
677             my $agent = $c->req->headers->user_agent;
678             my $custom = $c->req->headers->header('Custom-Header');
679             my $bytes = $c->req->body;
680             my $str = $c->req->text;
681             my $hash = $c->req->params->to_hash;
682             my $all = $c->req->uploads;
683             my $value = $c->req->json;
684             my $foo = $c->req->json('/23/foo');
685             my $dom = $c->req->dom;
686             my $bar = $c->req->dom('div.bar')->first->text;
687              
688             =head2 res
689              
690             my $res = $c->res;
691              
692             Get L object from L.
693              
694             # Longer version
695             my $res = $c->tx->res;
696              
697             # Force file download by setting a response header
698             $c->res->headers->content_disposition('attachment; filename=foo.png;');
699              
700             # Use a custom response header
701             $c->res->headers->header('Custom-Header' => 'whatever');
702              
703             # Make sure response is cached correctly
704             $c->res->headers->cache_control('public, max-age=300');
705             $c->res->headers->append(Vary => 'Accept-Encoding');
706              
707             =head2 send
708              
709             $c = $c->send({binary => $bytes});
710             $c = $c->send({text => $bytes});
711             $c = $c->send({json => {test => [1, 2, 3]}});
712             $c = $c->send([$fin, $rsv1, $rsv2, $rsv3, $op, $payload]);
713             $c = $c->send($chars);
714             $c = $c->send($chars => sub ($c) {...});
715              
716             Send message or frame non-blocking via WebSocket, the optional drain callback will be executed once all data has been
717             written. This method will automatically respond to WebSocket handshake requests with a C<101> response status, to
718             establish the WebSocket connection.
719              
720             # Send "Text" message
721             $c->send('I ♥ Mojolicious!');
722              
723             # Send JSON object as "Text" message
724             $c->send({json => {test => 'I ♥ Mojolicious!'}});
725              
726             # Send JSON object as "Binary" message
727             use Mojo::JSON qw(encode_json);
728             $c->send({binary => encode_json({test => 'I ♥ Mojolicious!'})});
729              
730             # Send "Ping" frame
731             use Mojo::WebSocket qw(WS_PING);
732             $c->send([1, 0, 0, 0, WS_PING, 'Hello World!']);
733              
734             # Make sure the first message has been written before continuing
735             $c->send('First message!' => sub ($c) { $c->send('Second message!') });
736              
737             For mostly idle WebSockets you might also want to increase the inactivity timeout with
738             L, which usually defaults to C<30> seconds.
739              
740             # Increase inactivity timeout for connection to 300 seconds
741             $c->inactivity_timeout(300);
742              
743             =head2 session
744              
745             my $session = $c->session;
746             my $foo = $c->session('foo');
747             $c = $c->session({foo => 'bar'});
748             $c = $c->session(foo => 'bar');
749              
750             Persistent data storage for the next few requests, all session data gets serialized with L and stored
751             Base64 encoded in HMAC-SHA256 signed cookies, to prevent tampering. Note that cookies usually have a C<4096> byte
752             (4KiB) limit, depending on browser.
753              
754             # Manipulate session
755             $c->session->{foo} = 'bar';
756             my $foo = $c->session->{foo};
757             delete $c->session->{foo};
758              
759             # Expiration date in seconds from now (persists between requests)
760             $c->session(expiration => 604800);
761              
762             # Expiration date as absolute epoch time (only valid for one request)
763             $c->session(expires => time + 604800);
764              
765             # Delete whole session by setting an expiration date in the past
766             $c->session(expires => 1);
767              
768             =head2 signed_cookie
769              
770             my $value = $c->signed_cookie('foo');
771             $c = $c->signed_cookie(foo => 'bar');
772             $c = $c->signed_cookie(foo => 'bar', {path => '/'});
773              
774             Access signed request cookie values and create new signed response cookies. If there are multiple values sharing the
775             same name, and you want to access more than just the last one, you can use L. Cookies are
776             cryptographically signed with HMAC-SHA256, to prevent tampering, and the ones failing signature verification will be
777             automatically discarded.
778              
779             =head2 stash
780              
781             my $hash = $c->stash;
782             my $foo = $c->stash('foo');
783             $c = $c->stash({foo => 'bar', baz => 23});
784             $c = $c->stash(foo => 'bar', baz => 23);
785              
786             Non-persistent data storage and exchange for the current request, application wide default values can be set with
787             L. Some stash values have a special meaning and are reserved, the full list is currently
788             C, C, C, C, C, C, C, C, C, C, C,
789             C, C, C, C