File Coverage

blib/lib/Mojolicious/Controller.pm
Criterion Covered Total %
statement 184 186 98.9
branch 93 98 94.9
condition 35 55 63.6
subroutine 108 108 100.0
pod 24 25 96.0
total 444 472 94.0


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