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   65253 use Mojo::Base -base;
  51         182  
  51         437  
3              
4             # No imports, for security reasons!
5 51     51   406 use Carp ();
  51         175  
  51         949  
6 51     51   321 use Digest::SHA ();
  51         124  
  51         951  
7 51     51   1201 use Mojo::ByteStream;
  51         145  
  51         2792  
8 51     51   1199 use Mojo::DynamicMethods -dispatch;
  51         174  
  51         517  
9 51     51   1295 use Mojo::URL;
  51         170  
  51         511  
10 51     51   372 use Mojo::Util;
  51         204  
  51         2579  
11 51     51   25081 use Mojolicious::Routes::Match;
  51         190  
  51         475  
12 51     51   510 use Scalar::Util ();
  51         148  
  51         180010  
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 6839 my ($class, $method, $dyn_methods) = @_;
19              
20             return sub {
21 503     503   3047 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         3275 my $dynamic = $dyn_methods->{$self->{app}{renderer}}{$method};
23 503 50       2407 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         21136 };
27             }
28              
29 1     1 1 13 sub continue { $_[0]->app->routes->continue($_[0]) }
30              
31             sub cookie {
32 148     148 1 754 my ($self, $name) = (shift, shift);
33              
34             # Response cookie
35 148 100       353 if (@_) {
36              
37             # Cookie too big
38 114   100     204 my $cookie = {name => $name, value => shift, %{shift // {}}};
  114         883  
39 114 50       435 $self->helpers->log->error(qq{Cookie "$name" is bigger than 4KiB}) if length $cookie->{value} > 4096;
40              
41 114         336 $self->res->cookies($cookie);
42 114         519 return $self;
43             }
44              
45             # Request cookies
46 34 100       83 return undef unless my $cookie = $self->req->cookie($name);
47 21         72 return $cookie->value;
48             }
49              
50 237     237 1 421 sub every_cookie { [map { $_->value } @{shift->req->every_cookie(shift)}] }
  68         175  
  237         581  
51              
52             sub every_param {
53 388     388 1 889 my ($self, $name) = @_;
54              
55             # Captured unreserved values
56 388   100     912 my $captures = $self->stash->{'mojo.captures'} //= {};
57 388 100 100     1622 if (exists $captures->{$name} && !$self->app->routes->is_reserved($name)) {
58 84         208 my $value = $captures->{$name};
59 84 100       739 return ref $value eq 'ARRAY' ? $value : [$value];
60             }
61              
62             # Uploads or param values
63 304         835 my $req = $self->req;
64 304         1414 my $uploads = $req->every_upload($name);
65 304 100       1378 return @$uploads ? $uploads : $req->every_param($name);
66             }
67              
68             sub every_signed_cookie {
69 235     235 1 543 my ($self, $name) = @_;
70              
71 235         546 my $secrets = $self->app->secrets;
72 235         508 my @results;
73 235         393 for my $value (@{$self->every_cookie($name)}) {
  235         751  
74              
75             # Check signature with rotating secrets
76 66 100       544 if ($value =~ s/--([^\-]+)$//) {
77 57         170 my $signature = $1;
78              
79 57         90 my $valid;
80 57         149 for my $secret (@$secrets) {
81 65         1215 my $check = Digest::SHA::hmac_sha256_hex("$name=$value", $secret);
82 65 100 50     295 ++$valid and last if Mojo::Util::secure_compare($signature, $check);
83             }
84 57 100       158 if ($valid) { push @results, $value }
  45         167  
85              
86 12         44 else { $self->helpers->log->trace(qq{Cookie "$name" has bad signature}) }
87             }
88              
89 9         28 else { $self->helpers->log->trace(qq{Cookie "$name" is not signed}) }
90             }
91              
92 235         1235 return \@results;
93             }
94              
95             sub finish {
96 18     18 1 142 my $self = shift;
97              
98             # WebSocket
99 18   33     92 my $tx = $self->tx || Carp::croak 'Transaction already destroyed';
100 18 100 50     70 $tx->finish(@_) and return $tx->established ? $self : $self->rendered(101) if $tx->is_websocket;
    100          
101              
102             # Chunked stream
103 9 100       41 return @_ ? $self->write_chunk(@_)->write_chunk('') : $self->write_chunk('') if $tx->res->content->is_chunked;
    100          
104              
105             # Normal stream
106 3 100       35 return @_ ? $self->write(@_)->write('') : $self->write('');
107             }
108              
109 4641     4641 1 13767 sub helpers { $_[0]->app->renderer->get_helper('')->($_[0]) }
110              
111             sub on {
112 93     93 1 644 my ($self, $name, $cb) = @_;
113 93   33     305 my $tx = $self->tx || Carp::croak 'Transaction already destroyed';
114 93 100 66     340 $self->rendered(101) if $tx->is_websocket && !$tx->established;
115 93     89   664 return $tx->on($name => sub { shift; $self->$cb(@_) });
  89         288  
  89         316  
116             }
117              
118             sub param {
119 261     261 1 1297 my ($self, $name) = (shift, shift);
120 261 100       1165 return $self->every_param($name)->[-1] unless @_;
121 27 100       108 $self->stash->{'mojo.captures'}{$name} = @_ > 1 ? [@_] : $_[0];
122 27         122 return $self;
123             }
124              
125             sub render {
126 958     958 1 2809 my $self = shift;
127              
128             # Template may be first argument
129 958 100       6072 my ($template, $args) = (@_ % 2 ? shift : undef, {@_});
130 958 100       2473 $args->{template} = $template if $template;
131 958         2688 my $app = $self->app;
132 958         2899 my $plugins = $app->plugins->emit_hook(before_render => $self, $args);
133              
134             # Localize "extends" and "layout" to allow argument overrides
135 958         2088 my ($maybe, $ts) = @{$args}{'mojo.maybe', 'mojo.string'};
  958         2636  
136 958         2327 my $stash = $self->stash;
137 958 100       3168 local $stash->{layout} = $stash->{layout} if exists $stash->{layout};
138 958 100       2554 local $stash->{extends} = $stash->{extends} if exists $stash->{extends};
139              
140             # Rendering to string
141 958 100 100     4985 local @{$stash}{keys %$args} if $ts || $maybe;
  558         2091  
142 958 100       2359 delete @{$stash}{qw(layout extends)} if $ts;
  26         85  
143              
144             # All other arguments just become part of the stash
145 958         3566 @$stash{keys %$args} = values %$args;
146 958         2894 my $renderer = $app->renderer;
147 958         3592 my ($output, $format) = $renderer->render($self);
148              
149             # Maybe no 404
150 938 50       3026 return defined $output ? Mojo::ByteStream->new($output) : undef if $ts;
    100          
151 913 100       7380 return $maybe ? undef : Carp::croak("Could not render a response") unless defined $output;
    100          
152              
153 732         3181 $plugins->emit_hook(after_render => $self, \$output, $format);
154 732         3790 return $renderer->respond($self, $output, $format, $stash->{status});
155             }
156              
157 956     956 1 2382 sub render_later { shift->stash('mojo.rendered' => 1) }
158              
159 537     537 1 1904 sub render_maybe { shift->render(@_, 'mojo.maybe' => 1) }
160              
161 26     26 1 206 sub render_to_string { shift->render(@_, 'mojo.string' => 1) }
162              
163             sub rendered {
164 1029     1029 1 2563 my ($self, $status) = @_;
165              
166             # Make sure we have a status
167 1029 100       2722 $self->res->code($status) if $status;
168              
169             # Finish transaction
170 1029         2643 my $stash = $self->stash;
171 1029 100 66     6122 if (!$stash->{'mojo.finished'} && ++$stash->{'mojo.finished'}) {
172 932         2525 my $res = $self->res;
173 932 100 100     4097 $res->code(200) if !$status && !$res->code;
174              
175             # Disable auto rendering and stop timer
176 932         2727 my $app = $self->render_later->app;
177             $self->helpers->log->trace(sub {
178 255     255   672 my $timing = $self->helpers->timing;
179 255   50     995 my $elapsed = $timing->elapsed('mojo.timer') // 0;
180 255   50     4775 my $rps = $timing->rps($elapsed) // '??';
181 255         885 my $code = $res->code;
182 255   33     880 my $msg = $res->message || $res->default_message($code);
183 255         2664 return "$code $msg (${elapsed}s, $rps/s)";
184 932 100       3847 }) unless $stash->{'mojo.static'};
185              
186 932         8830 $app->plugins->emit_hook_reverse(after_dispatch => $self);
187 932         3022 $app->sessions->store($self);
188             }
189 1029         2921 $self->tx->resume;
190 1029         9052 return $self;
191             }
192              
193 5419   33 5419 1 17032 sub req { (shift->tx || Carp::croak 'Transaction already destroyed')->req }
194 3378   33 3378 1 9290 sub res { (shift->tx || Carp::croak 'Transaction already destroyed')->res }
195              
196             sub send {
197 93     93 1 1202 my ($self, $msg, $cb) = @_;
198 93   33     597 my $tx = $self->tx || Carp::croak 'Transaction already destroyed';
199 93 100       447 Carp::croak 'No WebSocket connection to send message to' unless $tx->is_websocket;
200 92 100   2   415 $tx->send($msg, $cb ? sub { shift; $self->$cb(@_) } : ());
  2         17  
  2         21  
201 92 100       325 return $tx->established ? $self : $self->rendered(101);
202             }
203              
204             sub session {
205 229     229 1 601 my $self = shift;
206              
207 229         540 my $stash = $self->stash;
208 229 100       961 $self->app->sessions->load($self) unless exists $stash->{'mojo.active_session'};
209              
210             # Hash
211 229   100     1011 my $session = $stash->{'mojo.session'} //= {};
212 229 100       1006 return $session unless @_;
213              
214             # Get
215 39 100 66     184 return $session->{$_[0]} unless @_ > 1 || ref $_[0];
216              
217             # Set
218 21 50       593 my $values = ref $_[0] ? $_[0] : {@_};
219 21         93 @$session{keys %$values} = values %$values;
220              
221 21         75 return $self;
222             }
223              
224             sub signed_cookie {
225 301     301 1 1129 my ($self, $name, $value, $options) = @_;
226              
227             # Request cookie
228 301 100       1137 return $self->every_signed_cookie($name)->[-1] unless defined $value;
229              
230             # Response cookie
231 68         378 my $sum = Digest::SHA::hmac_sha256_hex("$name=$value", $self->app->secrets->[0]);
232 68         605 return $self->cookie($name, "$value--$sum", $options);
233             }
234              
235 19538     19538 1 52734 sub stash { Mojo::Util::_stash(stash => @_) }
236              
237             sub url_for {
238 576   100 576 1 2384 my ($self, $target) = (shift, shift // '');
239              
240             # Absolute URL
241 576 100 66     2408 return $target if Scalar::Util::blessed $target && $target->isa('Mojo::URL');
242 550 100       2787 return Mojo::URL->new($target) if $target =~ m!^(?:[^:/?#]+:|//|#)!;
243              
244             # Base
245 504         1839 my $url = Mojo::URL->new;
246 504         1584 my $req = $self->req;
247 504         1862 my $base = $url->base($req->url->base->clone)->base->userinfo(undef);
248              
249             # Relative URL
250 504         1462 my $path = $url->path;
251 504 100       2254 if ($target =~ m!^/!) {
252 340 100       923 if (defined(my $prefix = $self->stash->{path})) {
253 26         89 my $real = $req->url->path->to_route;
254 26         573 $real =~ s!/?\Q$prefix\E$!$target!;
255 26         88 $target = $real;
256             }
257 340         935 $url->parse($target);
258             }
259              
260             # Route
261             else {
262 164         587 my $generated = $self->match->path_for($target, @_);
263 164 100       1105 $path->parse($generated->{path}) if $generated->{path};
264 164 50       1039 $base->scheme($base->protocol eq 'https' ? 'wss' : 'ws') if $generated->{websocket};
    100          
265             }
266              
267             # Make path absolute
268 504         1389 my $base_path = $base->path;
269 504         1072 unshift @{$path->parts}, @{$base_path->parts};
  504         1368  
  504         1473  
270 504         1711 $base_path->parts([])->trailing_slash(0);
271              
272 504         2480 return $url;
273             }
274              
275             sub url_for_asset {
276 14     14 1 41 my ($self, $asset) = @_;
277 14         44 return $self->url_for($self->app->static->asset_path($asset));
278             }
279              
280             sub write {
281 21     21 1 165 my ($self, $chunk, $cb) = @_;
282 21 100   4   108 $self->res->content->write($chunk, $cb ? sub { shift; $self->$cb(@_) } : ());
  4         21  
  4         24  
283 21         79 return $self->rendered;
284             }
285              
286             sub write_chunk {
287 61     61 1 556 my ($self, $chunk, $cb) = @_;
288 61 100   37   189 $self->res->content->write_chunk($chunk, $cb ? sub { shift; $self->$cb(@_) } : ());
  37         102  
  37         140  
289 61         203 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