1Mojolicious::ControllerU(s3e)r Contributed Perl DocumentaMtoijoonlicious::Controller(3)
2
3
4
6 Mojolicious::Controller - Controller base class
7
9 # Controller
10 package MyApp::Controller::Foo;
11 use Mojo::Base 'Mojolicious::Controller', -signatures;
12
13 # Action
14 sub bar ($self) {
15 my $name = $self->param('name');
16 $self->res->headers->cache_control('max-age=1, no-cache');
17 $self->render(json => {hello => $name});
18 }
19
21 Mojolicious::Controller is the base class for your Mojolicious
22 controllers. It is also the default controller class unless you set
23 "controller_class" in Mojolicious.
24
26 Mojolicious::Controller implements the following attributes.
27
28 app
29 my $app = $c->app;
30 $c = $c->app(Mojolicious->new);
31
32 A reference back to the application that dispatched to this controller,
33 usually a Mojolicious object. Note that this attribute is weakened.
34
35 # Use application logger
36 $c->app->log->debug('Hello Mojo');
37
38 # Generate path
39 my $path = $c->app->home->child('templates', 'foo', 'bar.html.ep');
40
41 match
42 my $m = $c->match;
43 $c = $c->match(Mojolicious::Routes::Match->new);
44
45 Router results for the current request, defaults to a
46 Mojolicious::Routes::Match object.
47
48 # Introspect
49 my $name = $c->match->endpoint->name;
50 my $foo = $c->match->endpoint->pattern->defaults->{foo};
51 my $action = $c->match->stack->[-1]{action};
52
53 tx
54 my $tx = $c->tx;
55 $c = $c->tx(Mojo::Transaction::HTTP->new);
56
57 The transaction that is currently being processed, usually a
58 Mojo::Transaction::HTTP or Mojo::Transaction::WebSocket object. Note
59 that this attribute is weakened. So the object needs to be referenced
60 elsewhere as well when you're performing non-blocking operations and
61 the underlying connection might get closed early.
62
63 # Check peer information
64 my $address = $c->tx->remote_address;
65 my $port = $c->tx->remote_port;
66
67 # Increase size limit for WebSocket messages to 16MiB
68 $c->tx->max_websocket_size(16777216) if $c->tx->is_websocket;
69
70 # Perform non-blocking operation without knowing the connection status
71 my $tx = $c->tx;
72 Mojo::IOLoop->timer(2 => sub {
73 $c->app->log->debug($tx->is_finished ? 'Finished' : 'In progress');
74 });
75
77 Mojolicious::Controller inherits all methods from Mojo::Base and
78 implements the following new ones.
79
80 continue
81 $c->continue;
82
83 Continue dispatch chain from an intermediate destination with
84 "continue" in Mojolicious::Routes.
85
86 cookie
87 my $value = $c->cookie('foo');
88 $c = $c->cookie(foo => 'bar');
89 $c = $c->cookie(foo => 'bar', {path => '/'});
90
91 Access request cookie values and create new response cookies. If there
92 are multiple values sharing the same name, and you want to access more
93 than just the last one, you can use "every_cookie".
94
95 # Create response cookie with domain and expiration date
96 $c->cookie(user => 'sri', {domain => 'example.com', expires => time + 60});
97
98 # Create secure response cookie
99 $c->cookie(secret => 'I <3 Mojolicious', {secure => 1, httponly => 1});
100
101 every_cookie
102 my $values = $c->every_cookie('foo');
103
104 Similar to "cookie", but returns all request cookie values sharing the
105 same name as an array reference.
106
107 $ Get first cookie value
108 my $first = $c->every_cookie('foo')->[0];
109
110 every_param
111 my $values = $c->every_param('foo');
112
113 Similar to "param", but returns all values sharing the same name as an
114 array reference.
115
116 # Get first value
117 my $first = $c->every_param('foo')->[0];
118
119 every_signed_cookie
120 my $values = $c->every_signed_cookie('foo');
121
122 Similar to "signed_cookie", but returns all signed request cookie
123 values sharing the same name as an array reference.
124
125 # Get first signed cookie value
126 my $first = $c->every_signed_cookie('foo')->[0];
127
128 finish
129 $c = $c->finish;
130 $c = $c->finish(1000);
131 $c = $c->finish(1003 => 'Cannot accept data!');
132 $c = $c->finish('Bye!');
133
134 Close WebSocket connection or long poll stream gracefully. This method
135 will automatically respond to WebSocket handshake requests with a 101
136 response status, to establish the WebSocket connection.
137
138 helpers
139 my $helpers = $c->helpers;
140
141 Return a proxy object containing the current controller object and on
142 which helpers provided by "app" can be called. This includes all
143 helpers from Mojolicious::Plugin::DefaultHelpers and
144 Mojolicious::Plugin::TagHelpers.
145
146 # Make sure to use the "title" helper and not the controller method
147 $c->helpers->title('Welcome!');
148
149 # Use a nested helper instead of the "reply" controller method
150 $c->helpers->reply->not_found;
151
152 on
153 my $cb = $c->on(finish => sub {...});
154
155 Subscribe to events of "tx", which is usually a Mojo::Transaction::HTTP
156 or Mojo::Transaction::WebSocket object. This method will automatically
157 respond to WebSocket handshake requests with a 101 response status, to
158 establish the WebSocket connection.
159
160 # Do something after the transaction has been finished
161 $c->on(finish => sub ($c) {
162 $c->app->log->debug('All data has been sent');
163 });
164
165 # Receive WebSocket message
166 $c->on(message => sub ($c, $msg) {
167 $c->app->log->debug("Message: $msg");
168 });
169
170 # Receive JSON object via WebSocket message
171 $c->on(json => sub ($c, $hash) {
172 $c->app->log->debug("Test: $hash->{test}");
173 });
174
175 # Receive WebSocket "Binary" message
176 $c->on(binary => sub ($c, $bytes) {
177 my $len = length $bytes;
178 $c->app->log->debug("Received $len bytes");
179 });
180
181 param
182 my $value = $c->param('foo');
183 $c = $c->param(foo => 'ba;r');
184 $c = $c->param(foo => 'ba;r', 'baz');
185 $c = $c->param(foo => ['ba;r', 'baz']);
186
187 Access route placeholder values that are not reserved stash values,
188 file uploads as well as "GET" and "POST" parameters extracted from the
189 query string and "application/x-www-form-urlencoded" or
190 "multipart/form-data" message body, in that order. If there are
191 multiple values sharing the same name, and you want to access more than
192 just the last one, you can use "every_param". Parts of the request body
193 need to be loaded into memory to parse "POST" parameters, so you have
194 to make sure it is not excessively large. There's a 16MiB limit for
195 requests by default.
196
197 # Get first value
198 my $first = $c->every_param('foo')->[0];
199
200 For more control you can also access request information directly.
201
202 # Only GET parameters
203 my $foo = $c->req->query_params->param('foo');
204
205 # Only POST parameters
206 my $foo = $c->req->body_params->param('foo');
207
208 # Only GET and POST parameters
209 my $foo = $c->req->param('foo');
210
211 # Only file uploads
212 my $foo = $c->req->upload('foo');
213
214 render
215 my $bool = $c->render;
216 my $bool = $c->render(foo => 'bar', baz => 23);
217 my $bool = $c->render(template => 'foo/index');
218 my $bool = $c->render(template => 'index', format => 'html');
219 my $bool = $c->render(data => $bytes);
220 my $bool = $c->render(text => 'Hello!');
221 my $bool = $c->render(json => {foo => 'bar'});
222 my $bool = $c->render(handler => 'something');
223 my $bool = $c->render('foo/index');
224
225 Render content with "renderer" in Mojolicious and emit hooks
226 "before_render" in Mojolicious as well as "after_render" in
227 Mojolicious, or call "reply->not_found" in
228 Mojolicious::Plugin::DefaultHelpers if no response could be generated,
229 all additional key/value pairs get merged into the "stash".
230
231 # Render characters
232 $c->render(text => 'I ♥ Mojolicious!');
233
234 # Render characters (alternative)
235 $c->stash(text => 'I ♥ Mojolicious!')->render;
236
237 # Render binary data
238 use Mojo::JSON qw(encode_json);
239 $c->render(data => encode_json({test => 'I ♥ Mojolicious!'}));
240
241 # Render JSON
242 $c->render(json => {test => 'I ♥ Mojolicious!'});
243
244 # Render inline template
245 $c->render(inline => '<%= 1 + 1 %>');
246
247 # Render template "foo/bar.html.ep"
248 $c->render(template => 'foo/bar', format => 'html', handler => 'ep');
249
250 # Render template "test.*.*" with arbitrary values "foo" and "bar"
251 $c->render(template => 'test', foo => 'test', bar => 23);
252
253 # Render template "test.xml.*"
254 $c->render(template => 'test', format => 'xml');
255
256 # Render template "test.xml.*" (alternative)
257 $c->render('test', format => 'xml');
258
259 render_later
260 $c = $c->render_later;
261
262 Disable automatic rendering to delay response generation, only
263 necessary if automatic rendering would result in a response.
264
265 # Delayed rendering
266 $c->render_later;
267 Mojo::IOLoop->timer(2 => sub { $c->render(text => 'Delayed by 2 seconds!') });
268
269 render_maybe
270 my $bool = $c->render_maybe;
271 my $bool = $c->render_maybe(foo => 'bar', baz => 23);
272 my $bool = $c->render_maybe('foo/index', format => 'html');
273
274 Try to render content, but do not call "reply->not_found" in
275 Mojolicious::Plugin::DefaultHelpers if no response could be generated,
276 all arguments get localized automatically and are only available during
277 this render operation, takes the same arguments as "render".
278
279 # Render template "index_local" only if it exists
280 $c->render_maybe('index_local') or $c->render('index');
281
282 render_to_string
283 my $output = $c->render_to_string('foo/index', format => 'pdf');
284
285 Try to render content and return it wrapped in a Mojo::ByteStream
286 object or return "undef", all arguments get localized automatically and
287 are only available during this render operation, takes the same
288 arguments as "render".
289
290 # Render inline template
291 my $two = $c->render_to_string(inline => '<%= 1 + 1 %>');
292
293 rendered
294 $c = $c->rendered;
295 $c = $c->rendered(302);
296
297 Finalize response and emit hook "after_dispatch" in Mojolicious,
298 defaults to using a 200 response code.
299
300 # Custom response
301 $c->res->headers->content_type('text/plain');
302 $c->res->body('Hello World!');
303 $c->rendered(200);
304
305 req
306 my $req = $c->req;
307
308 Get Mojo::Message::Request object from "tx".
309
310 # Longer version
311 my $req = $c->tx->req;
312
313 # Extract request information
314 my $id = $c->req->request_id;
315 my $method = $c->req->method;
316 my $url = $c->req->url->to_abs;
317 my $info = $c->req->url->to_abs->userinfo;
318 my $host = $c->req->url->to_abs->host;
319 my $agent = $c->req->headers->user_agent;
320 my $custom = $c->req->headers->header('Custom-Header');
321 my $bytes = $c->req->body;
322 my $str = $c->req->text;
323 my $hash = $c->req->params->to_hash;
324 my $all = $c->req->uploads;
325 my $value = $c->req->json;
326 my $foo = $c->req->json('/23/foo');
327 my $dom = $c->req->dom;
328 my $bar = $c->req->dom('div.bar')->first->text;
329
330 res
331 my $res = $c->res;
332
333 Get Mojo::Message::Response object from "tx".
334
335 # Longer version
336 my $res = $c->tx->res;
337
338 # Force file download by setting a response header
339 $c->res->headers->content_disposition('attachment; filename=foo.png;');
340
341 # Use a custom response header
342 $c->res->headers->header('Custom-Header' => 'whatever');
343
344 # Make sure response is cached correctly
345 $c->res->headers->cache_control('public, max-age=300');
346 $c->res->headers->append(Vary => 'Accept-Encoding');
347
348 send
349 $c = $c->send({binary => $bytes});
350 $c = $c->send({text => $bytes});
351 $c = $c->send({json => {test => [1, 2, 3]}});
352 $c = $c->send([$fin, $rsv1, $rsv2, $rsv3, $op, $payload]);
353 $c = $c->send($chars);
354 $c = $c->send($chars => sub ($c) {...});
355
356 Send message or frame non-blocking via WebSocket, the optional drain
357 callback will be executed once all data has been written. This method
358 will automatically respond to WebSocket handshake requests with a 101
359 response status, to establish the WebSocket connection.
360
361 # Send "Text" message
362 $c->send('I ♥ Mojolicious!');
363
364 # Send JSON object as "Text" message
365 $c->send({json => {test => 'I ♥ Mojolicious!'}});
366
367 # Send JSON object as "Binary" message
368 use Mojo::JSON qw(encode_json);
369 $c->send({binary => encode_json({test => 'I ♥ Mojolicious!'})});
370
371 # Send "Ping" frame
372 use Mojo::WebSocket qw(WS_PING);
373 $c->send([1, 0, 0, 0, WS_PING, 'Hello World!']);
374
375 # Make sure the first message has been written before continuing
376 $c->send('First message!' => sub ($c) { $c->send('Second message!') });
377
378 For mostly idle WebSockets you might also want to increase the
379 inactivity timeout with "inactivity_timeout" in
380 Mojolicious::Plugin::DefaultHelpers, which usually defaults to 30
381 seconds.
382
383 # Increase inactivity timeout for connection to 300 seconds
384 $c->inactivity_timeout(300);
385
386 session
387 my $session = $c->session;
388 my $foo = $c->session('foo');
389 $c = $c->session({foo => 'bar'});
390 $c = $c->session(foo => 'bar');
391
392 Persistent data storage for the next few requests, all session data
393 gets serialized with Mojo::JSON and stored Base64 encoded in HMAC-SHA1
394 signed cookies, to prevent tampering. Note that cookies usually have a
395 4096 byte (4KiB) limit, depending on browser.
396
397 # Manipulate session
398 $c->session->{foo} = 'bar';
399 my $foo = $c->session->{foo};
400 delete $c->session->{foo};
401
402 # Expiration date in seconds from now (persists between requests)
403 $c->session(expiration => 604800);
404
405 # Expiration date as absolute epoch time (only valid for one request)
406 $c->session(expires => time + 604800);
407
408 # Delete whole session by setting an expiration date in the past
409 $c->session(expires => 1);
410
411 signed_cookie
412 my $value = $c->signed_cookie('foo');
413 $c = $c->signed_cookie(foo => 'bar');
414 $c = $c->signed_cookie(foo => 'bar', {path => '/'});
415
416 Access signed request cookie values and create new signed response
417 cookies. If there are multiple values sharing the same name, and you
418 want to access more than just the last one, you can use
419 "every_signed_cookie". Cookies are cryptographically signed with
420 HMAC-SHA1, to prevent tampering, and the ones failing signature
421 verification will be automatically discarded.
422
423 stash
424 my $hash = $c->stash;
425 my $foo = $c->stash('foo');
426 $c = $c->stash({foo => 'bar', baz => 23});
427 $c = $c->stash(foo => 'bar', baz => 23);
428
429 Non-persistent data storage and exchange for the current request,
430 application wide default values can be set with "defaults" in
431 Mojolicious. Some stash values have a special meaning and are reserved,
432 the full list is currently "action", "app", "cb", "controller", "data",
433 "extends", "format", "handler", "inline", "json", "layout",
434 "namespace", "path", "status", "template", "text" and "variant". Note
435 that all stash values with a "mojo.*" prefix are reserved for internal
436 use.
437
438 # Remove value
439 my $foo = delete $c->stash->{foo};
440
441 # Assign multiple values at once
442 $c->stash(foo => 'test', bar => 23);
443
444 url_for
445 my $url = $c->url_for;
446 my $url = $c->url_for(name => 'sebastian');
447 my $url = $c->url_for({name => 'sebastian'});
448 my $url = $c->url_for('test', name => 'sebastian');
449 my $url = $c->url_for('test', {name => 'sebastian'});
450 my $url = $c->url_for('/index.html');
451 my $url = $c->url_for('//example.com/index.html');
452 my $url = $c->url_for('http://example.com/index.html');
453 my $url = $c->url_for('mailto:sri@example.com');
454 my $url = $c->url_for('#whatever');
455
456 Generate a portable Mojo::URL object with base for a path, URL or
457 route.
458
459 # Rebuild URL for the current route
460 $c->url_for;
461
462 # Rebuild URL for the current route, but replace the "name" placeholder value
463 $c->url_for(name => 'sebastian');
464
465 # Absolute URL for the current route
466 $c->url_for->to_abs;
467
468 # Build URL for route "test" with two placeholder values
469 $c->url_for('test', name => 'sebastian', foo => 'bar');
470
471 # "http://127.0.0.1:3000/index.html" if application was started with Morbo
472 $c->url_for('/index.html')->to_abs;
473
474 # "https://127.0.0.1:443/index.html" if application was started with Morbo
475 $c->url_for('/index.html')->to_abs->scheme('https')->port(443);
476
477 # "/index.html?foo=bar" if application is deployed under "/"
478 $c->url_for('/index.html')->query(foo => 'bar');
479
480 # "/myapp/index.html?foo=bar" if application is deployed under "/myapp"
481 $c->url_for('/index.html')->query(foo => 'bar');
482
483 You can also use the helper "url_with" in
484 Mojolicious::Plugin::DefaultHelpers to inherit query parameters from
485 the current request.
486
487 # "/list?q=mojo&page=2" if current request was for "/list?q=mojo&page=1"
488 $c->url_with->query({page => 2});
489
490 write
491 $c = $c->write;
492 $c = $c->write('');
493 $c = $c->write($bytes);
494 $c = $c->write($bytes => sub ($c) {...});
495
496 Write dynamic content non-blocking, the optional drain callback will be
497 executed once all data has been written. Calling this method without a
498 chunk of data will finalize the response headers and allow for dynamic
499 content to be written later.
500
501 # Keep connection alive (with Content-Length header)
502 $c->res->headers->content_length(6);
503 $c->write('Hel' => sub ($c) { $c->write('lo!') });
504
505 # Close connection when finished (without Content-Length header)
506 $c->write('Hel' => sub ($c) {
507 $c->write('lo!' => sub ($c) { $c->finish });
508 });
509
510 You can call "finish" or write an empty chunk of data at any time to
511 end the stream.
512
513 HTTP/1.1 200 OK
514 Date: Sat, 13 Sep 2014 16:48:29 GMT
515 Content-Length: 6
516 Server: Mojolicious (Perl)
517
518 Hello!
519
520 HTTP/1.1 200 OK
521 Connection: close
522 Date: Sat, 13 Sep 2014 16:48:29 GMT
523 Server: Mojolicious (Perl)
524
525 Hello!
526
527 For Comet (long polling) you might also want to increase the inactivity
528 timeout with "inactivity_timeout" in
529 Mojolicious::Plugin::DefaultHelpers, which usually defaults to 30
530 seconds.
531
532 # Increase inactivity timeout for connection to 300 seconds
533 $c->inactivity_timeout(300);
534
535 write_chunk
536 $c = $c->write_chunk;
537 $c = $c->write_chunk('');
538 $c = $c->write_chunk($bytes);
539 $c = $c->write_chunk($bytes => sub ($c) {...});
540
541 Write dynamic content non-blocking with chunked transfer encoding, the
542 optional drain callback will be executed once all data has been
543 written. Calling this method without a chunk of data will finalize the
544 response headers and allow for dynamic content to be written later.
545
546 # Make sure previous chunk has been written before continuing
547 $c->write_chunk('H' => sub ($c) {
548 $c->write_chunk('ell' => sub ($c) { $c->finish('o!') });
549 });
550
551 You can call "finish" or write an empty chunk of data at any time to
552 end the stream.
553
554 HTTP/1.1 200 OK
555 Date: Sat, 13 Sep 2014 16:48:29 GMT
556 Transfer-Encoding: chunked
557 Server: Mojolicious (Perl)
558
559 1
560 H
561 3
562 ell
563 2
564 o!
565 0
566
568 In addition to the "ATTRIBUTES" and "METHODS" above you can also call
569 helpers provided by "app" on Mojolicious::Controller objects. This
570 includes all helpers from Mojolicious::Plugin::DefaultHelpers and
571 Mojolicious::Plugin::TagHelpers.
572
573 # Call helpers
574 $c->layout('green');
575 $c->title('Welcome!');
576
577 # Longer version
578 $c->helpers->layout('green');
579
581 Mojolicious, Mojolicious::Guides, <https://mojolicious.org>.
582
583
584
585perl v5.32.1 2021-02-07 Mojolicious::Controller(3)