1Mojolicious::Guides::CoUoskebrooCko(n3t)ributed Perl DocMuomjeonltiactiioouns::Guides::Cookbook(3)
2
3
4
6 Mojolicious::Guides::Cookbook - Cooking with Mojolicious
7
9 This document contains many fun recipes for cooking with Mojolicious.
10
12 Essentials every Mojolicious developer should know.
13
14 Blocking and non-blocking operations
15 A blocking operation is a subroutine that blocks the execution of the
16 calling subroutine until the subroutine is finished.
17
18 sub foo {
19 my $result = blocking_subroutine();
20 ...
21 }
22
23 A non-blocking operation on the other hand lets the calling subroutine
24 continue execution even though the subroutine is not yet finished.
25 Instead of waiting, the calling subroutine passes along a callback to
26 be executed once the subroutine is finished, this is called
27 continuation-passing style.
28
29 sub foo {
30 non_blocking_subroutine(sub {
31 my $result = shift;
32 ...
33 });
34 ...
35 }
36
37 While Mojolicious has been designed from the ground up for non-blocking
38 I/O and event loops, it is not possible to magically make Perl code
39 non-blocking. You have to use specialized non-blocking code available
40 through modules like Mojo::IOLoop and Mojo::UserAgent, or third-party
41 event loops. You can wrap your blocking code in subprocesses though to
42 prevent it from interfering with your non-blocking code.
43
44 Event loops
45 An event loop is basically a loop that continually tests for external
46 events and executes the appropriate callbacks to handle them, it is
47 often the main loop in a program. Non-blocking tests for
48 readability/writability of file descriptors and timers are commonly
49 used events for highly scalable network servers, because they allow a
50 single process to handle thousands of client connections concurrently.
51
52 while (1) {
53 my @readable = test_fds_for_readability();
54 handle_readable_fds(@readable);
55
56 my @writable = test_fds_for_writability();
57 handle_writable_fds(@writable);
58
59 my @expired = test_timers();
60 handle_timers(@expired);
61 }
62
63 In Mojolicious this event loop is Mojo::IOLoop.
64
65 Reverse proxy
66 A reverse proxy architecture is a deployment technique used in many
67 production environments, where a reverse proxy server is put in front
68 of your application to act as the endpoint accessible by external
69 clients. It can provide a lot of benefits, like terminating SSL
70 connections from the outside, limiting the number of concurrent open
71 sockets towards the Mojolicious application (or even using Unix
72 sockets), balancing load across multiple instances, or supporting
73 several applications through the same IP/port.
74
75 ..........................................
76 : :
77 +--------+ : +-----------+ +---------------+ :
78 | |-------->| | | | :
79 | client | : | reverse |----->| Mojolicious | :
80 | |<--------| proxy | | application | :
81 +--------+ : | |<-----| | :
82 : +-----------+ +---------------+ :
83 : :
84 .. system boundary (e.g. same host) ......
85
86 This setup introduces some problems, though: the application will
87 receive requests from the reverse proxy instead of the original client;
88 the address/hostname where your application lives internally will be
89 different from the one visible from the outside; and if terminating
90 SSL, the reverse proxy exposes services via HTTPS while using HTTP
91 towards the Mojolicious application.
92
93 As an example, compare a sample request from the client and what the
94 Mojolicious application receives:
95
96 client reverse proxy Mojolicious app
97 __|__ _______________|______________ ____|____
98 / \ / \ / \
99 1.2.3.4 --HTTPS--> api.example.com 10.20.30.39 --HTTP--> 10.20.30.40
100
101 GET /foo/1 HTTP/1.1 | GET /foo/1 HTTP/1.1
102 Host: api.example.com | Host: 10.20.30.40
103 User-Agent: Firefox | User-Agent: ShinyProxy/1.2
104 ... | ...
105
106 However, now the client address is no longer available (which might be
107 useful for analytics, or Geo-IP) and URLs generated via "url_for" in
108 Mojolicious::Controller will look like this:
109
110 http://10.20.30.40/bar/2
111
112 instead of something meaningful for the client, like this:
113
114 https://api.example.com/bar/2
115
116 To solve these problems, you can configure your reverse proxy to send
117 the missing data (see "Nginx" and "Apache/mod_proxy") and tell your
118 application about it by setting the environment variable
119 "MOJO_REVERSE_PROXY". For finer control, "Rewriting" includes examples
120 of how the changes could be implemented manually.
121
123 Getting Mojolicious and Mojolicious::Lite applications running on
124 different platforms. Note that many real-time web features are based on
125 the Mojo::IOLoop event loop, and therefore require one of the built-in
126 web servers to be able to use them to their full potential.
127
128 Built-in web server
129 Mojolicious contains a very portable non-blocking I/O HTTP and
130 WebSocket server with Mojo::Server::Daemon. It is usually used during
131 development and in the construction of more advanced web servers, but
132 is solid and fast enough for small to mid sized applications.
133
134 $ ./script/my_app daemon
135 Server available at http://127.0.0.1:3000
136
137 It is available to every application through the command
138 Mojolicious::Command::daemon, which has many configuration options and
139 is known to work on every platform Perl works on with its single-
140 process architecture.
141
142 $ ./script/my_app daemon -h
143 ...List of available options...
144
145 Another huge advantage is that it supports TLS and WebSockets out of
146 the box, a development certificate for testing purposes is built right
147 in, so it just works, but you can specify all listen locations
148 supported by "listen" in Mojo::Server::Daemon.
149
150 $ ./script/my_app daemon -l https://[::]:3000
151 Server available at https://[::]:3000
152
153 To manage the web server with systemd, you can use a unit configuration
154 file like this.
155
156 [Unit]
157 Description=My Mojolicious application
158 After=network.target
159
160 [Service]
161 Type=simple
162 ExecStart=/home/sri/myapp/script/my_app daemon -m production -l http://*:8080
163
164 [Install]
165 WantedBy=multi-user.target
166
167 Pre-forking
168 On UNIX platforms you can also add pre-forking to the built-in web
169 server and switch to a multi-process architecture with
170 Mojolicious::Command::prefork, to take advantage of multiple CPU cores
171 and copy-on-write memory management.
172
173 $ ./script/my_app prefork
174 Server available at http://127.0.0.1:3000
175
176 Since all built-in web servers are based on the Mojo::IOLoop event
177 loop, they scale best with non-blocking operations. But if your
178 application for some reason needs to perform many blocking operations,
179 you can improve performance by increasing the number of worker
180 processes and decreasing the number of concurrent connections each
181 worker is allowed to handle (often as low as 1).
182
183 $ ./script/my_app prefork -m production -w 10 -c 1
184 Server available at http://127.0.0.1:3000
185
186 During startup your application is preloaded in the manager process,
187 which does not run an event loop, so you can use "next_tick" in
188 Mojo::IOLoop to run code whenever a new worker process has been forked
189 and its event loop gets started.
190
191 use Mojolicious::Lite;
192
193 Mojo::IOLoop->next_tick(sub {
194 app->log->info("Worker $$ star...ALL GLORY TO THE HYPNOTOAD!");
195 });
196
197 get '/' => {text => 'Hello Wor...ALL GLORY TO THE HYPNOTOAD!'};
198
199 app->start;
200
201 And to manage the pre-forking web server with systemd, you can use a
202 unit configuration file like this.
203
204 [Unit]
205 Description=My Mojolicious application
206 After=network.target
207
208 [Service]
209 Type=simple
210 ExecStart=/home/sri/myapp/script/my_app prefork -m production -l http://*:8080
211
212 [Install]
213 WantedBy=multi-user.target
214
215 Morbo
216 After reading the Mojolicious::Guides::Tutorial, you should already be
217 familiar with Mojo::Server::Morbo.
218
219 Mojo::Server::Morbo
220 +- Mojo::Server::Daemon
221
222 It is basically a restarter that forks a new Mojo::Server::Daemon web
223 server whenever a file in your project changes, and should therefore
224 only be used during development. To start applications with it you can
225 use the morbo script.
226
227 $ morbo ./script/my_app
228 Server available at http://127.0.0.1:3000
229
230 Hypnotoad
231 For bigger applications Mojolicious contains the UNIX optimized pre-
232 forking web server Hypnotoad, which can take advantage of multiple CPU
233 cores and copy-on-write memory management to scale up to thousands of
234 concurrent client connections.
235
236 Mojo::Server::Hypnotoad
237 |- Mojo::Server::Daemon [1]
238 |- Mojo::Server::Daemon [2]
239 |- Mojo::Server::Daemon [3]
240 +- Mojo::Server::Daemon [4]
241
242 It is based on the Mojo::Server::Prefork web server, which adds pre-
243 forking to Mojo::Server::Daemon, but optimized specifically for
244 production environments out of the box. To start applications with it
245 you can use the hypnotoad script, which listens on port 8080,
246 automatically daemonizes the server process and defaults to
247 "production" mode for Mojolicious and Mojolicious::Lite applications.
248
249 $ hypnotoad ./script/my_app
250
251 Many configuration settings can be tweaked right from within your
252 application with "config" in Mojolicious, for a full list see
253 "SETTINGS" in Mojo::Server::Hypnotoad.
254
255 use Mojolicious::Lite;
256
257 app->config(hypnotoad => {listen => ['http://*:80']});
258
259 get '/' => {text => 'Hello Wor...ALL GLORY TO THE HYPNOTOAD!'};
260
261 app->start;
262
263 Or just add a "hypnotoad" section to your Mojolicious::Plugin::Config
264 or Mojolicious::Plugin::JSONConfig configuration file.
265
266 # myapp.conf
267 {
268 hypnotoad => {
269 listen => ['https://*:443?cert=/etc/server.crt&key=/etc/server.key'],
270 workers => 10
271 }
272 };
273
274 But one of its biggest advantages is the support for effortless zero
275 downtime software upgrades (hot deployment). That means you can upgrade
276 Mojolicious, Perl or even system libraries at runtime without ever
277 stopping the server or losing a single incoming connection, just by
278 running the command above again.
279
280 $ hypnotoad ./script/my_app
281 Starting hot deployment for Hypnotoad server 31841.
282
283 You might also want to enable proxy support if you're using Hypnotoad
284 behind a reverse proxy. This allows Mojolicious to automatically pick
285 up the "X-Forwarded-For" and "X-Forwarded-Proto" headers.
286
287 # myapp.conf
288 {hypnotoad => {proxy => 1}};
289
290 To manage Hypnotoad with systemd, you can use a unit configuration file
291 like this.
292
293 [Unit]
294 Description=My Mojolicious application
295 After=network.target
296
297 [Service]
298 Type=forking
299 PIDFile=/home/sri/myapp/script/hypnotoad.pid
300 ExecStart=/path/to/hypnotoad /home/sri/myapp/script/my_app
301 ExecReload=/path/to/hypnotoad /home/sri/myapp/script/my_app
302 KillMode=process
303
304 [Install]
305 WantedBy=multi-user.target
306
307 Zero downtime software upgrades
308 Hypnotoad makes zero downtime software upgrades (hot deployment) very
309 simple, as you can see above, but on modern operating systems that
310 support the "SO_REUSEPORT" socket option, there is also another method
311 available that works with all built-in web servers.
312
313 $ ./script/my_app prefork -P /tmp/first.pid -l http://*:8080?reuse=1
314 Server available at http://127.0.0.1:8080
315
316 All you have to do, is to start a second web server listening to the
317 same port, and stop the first web server gracefully afterwards.
318
319 $ ./script/my_app prefork -P /tmp/second.pid -l http://*:8080?reuse=1
320 Server available at http://127.0.0.1:8080
321 $ kill -s TERM `cat /tmp/first.pid`
322
323 Just remember that both web servers need to be started with the "reuse"
324 parameter.
325
326 Nginx
327 One of the most popular setups these days is Hypnotoad behind an Nginx
328 <http://nginx.org> reverse proxy, which even supports WebSockets in
329 newer versions.
330
331 upstream myapp {
332 server 127.0.0.1:8080;
333 }
334 server {
335 listen 80;
336 server_name localhost;
337 location / {
338 proxy_pass http://myapp;
339 proxy_http_version 1.1;
340 proxy_set_header Upgrade $http_upgrade;
341 proxy_set_header Connection "upgrade";
342 proxy_set_header Host $host;
343 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
344 proxy_set_header X-Forwarded-Proto $scheme;
345 }
346 }
347
348 Apache/mod_proxy
349 Another good reverse proxy is Apache <http://httpd.apache.org> with
350 "mod_proxy", the configuration looks quite similar to the Nginx one
351 above. And if you need WebSocket support, newer versions come with
352 "mod_proxy_wstunnel".
353
354 <VirtualHost *:80>
355 ServerName localhost
356 <Proxy *>
357 Require all granted
358 </Proxy>
359 ProxyRequests Off
360 ProxyPreserveHost On
361 ProxyPass /echo ws://localhost:8080/echo
362 ProxyPass / http://localhost:8080/ keepalive=On
363 ProxyPassReverse / http://localhost:8080/
364 RequestHeader set X-Forwarded-Proto "http"
365 </VirtualHost>
366
367 Apache/CGI
368 "CGI" is supported out of the box and your Mojolicious application will
369 automatically detect that it is executed as a "CGI" script. Its use in
370 production environments is discouraged though, because as a result of
371 how "CGI" works, it is very slow and many web servers are making it
372 exceptionally hard to configure properly. Additionally, many real-time
373 web features, such as WebSockets, are not available.
374
375 ScriptAlias / /home/sri/my_app/script/my_app/
376
377 PSGI/Plack
378 PSGI is an interface between Perl web frameworks and web servers, and
379 Plack is a Perl module and toolkit that contains PSGI middleware,
380 helpers and adapters to web servers. PSGI and Plack are inspired by
381 Python's WSGI and Ruby's Rack. Mojolicious applications are
382 ridiculously simple to deploy with Plack, but be aware that many real-
383 time web features, such as WebSockets, are not available.
384
385 $ plackup ./script/my_app
386
387 Plack provides many server and protocol adapters for you to choose
388 from, such as "FCGI", "uWSGI" and "mod_perl".
389
390 $ plackup ./script/my_app -s FCGI -l /tmp/myapp.sock
391
392 The "MOJO_REVERSE_PROXY" environment variable can be used to enable
393 proxy support, this allows Mojolicious to automatically pick up the
394 "X-Forwarded-For" and "X-Forwarded-Proto" headers.
395
396 $ MOJO_REVERSE_PROXY=1 plackup ./script/my_app
397
398 If an older server adapter is unable to correctly detect the
399 application home directory, you can simply use the "MOJO_HOME"
400 environment variable.
401
402 $ MOJO_HOME=/home/sri/my_app plackup ./script/my_app
403
404 There is no need for a ".psgi" file, just point the server adapter at
405 your application script, it will automatically act like one if it
406 detects the presence of a "PLACK_ENV" environment variable.
407
408 Plack middleware
409 Wrapper scripts like "myapp.fcgi" are a great way to separate
410 deployment and application logic.
411
412 #!/usr/bin/env plackup -s FCGI
413 use Plack::Builder;
414
415 builder {
416 enable 'Deflater';
417 require './script/my_app';
418 };
419
420 Mojo::Server::PSGI can be used directly to load and customize
421 applications in the wrapper script.
422
423 #!/usr/bin/env plackup -s FCGI
424 use Mojo::Server::PSGI;
425 use Plack::Builder;
426
427 builder {
428 enable 'Deflater';
429 my $server = Mojo::Server::PSGI->new;
430 $server->load_app('./script/my_app');
431 $server->app->config(foo => 'bar');
432 $server->to_psgi_app;
433 };
434
435 But you could even use middleware right in your application.
436
437 use Mojolicious::Lite;
438 use Plack::Builder;
439
440 get '/welcome' => sub {
441 my $c = shift;
442 $c->render(text => 'Hello Mojo!');
443 };
444
445 builder {
446 enable 'Deflater';
447 app->start;
448 };
449
450 Rewriting
451 Sometimes you might have to deploy your application in a blackbox
452 environment where you can't just change the server configuration or
453 behind a reverse proxy that passes along additional information with
454 "X-Forwarded-*" headers. In such cases you can use the hook
455 "before_dispatch" in Mojolicious to rewrite incoming requests.
456
457 # Change scheme if "X-Forwarded-HTTPS" header is set
458 $app->hook(before_dispatch => sub {
459 my $c = shift;
460 $c->req->url->base->scheme('https')
461 if $c->req->headers->header('X-Forwarded-HTTPS');
462 });
463
464 Since reverse proxies generally don't pass along information about path
465 prefixes your application might be deployed under, rewriting the base
466 path of incoming requests is also quite common. This allows "url_for"
467 in Mojolicious::Controller for example, to generate portable URLs based
468 on the current environment.
469
470 # Move first part and slash from path to base path in production mode
471 $app->hook(before_dispatch => sub {
472 my $c = shift;
473 push @{$c->req->url->base->path->trailing_slash(1)},
474 shift @{$c->req->url->path->leading_slash(0)};
475 }) if $app->mode eq 'production';
476
477 Mojo::URL objects are very easy to manipulate, just make sure that the
478 URL ("foo/bar?baz=yada"), which represents the routing destination, is
479 always relative to the base URL ("http://example.com/myapp/"), which
480 represents the deployment location of your application.
481
482 Application embedding
483 From time to time you might want to reuse parts of Mojolicious
484 applications like configuration files, database connection or helpers
485 for other scripts, with this little Mojo::Server based mock server you
486 can just embed them.
487
488 use Mojo::Server;
489
490 # Load application with mock server
491 my $server = Mojo::Server->new;
492 my $app = $server->load_app('./myapp.pl');
493
494 # Access fully initialized application
495 say for @{$app->static->paths};
496 say $app->config->{secret_identity};
497 say $app->dumper({just => 'a helper test'});
498 say $app->build_controller->render_to_string(template => 'foo');
499
500 The plugin Mojolicious::Plugin::Mount uses this functionality to allow
501 you to combine multiple applications into one and deploy them together.
502
503 use Mojolicious::Lite;
504
505 app->config(hypnotoad => {listen => ['http://*:80']});
506
507 plugin Mount => {'test1.example.com' => '/home/sri/myapp1.pl'};
508 plugin Mount => {'test2.example.com' => '/home/sri/myapp2.pl'};
509
510 app->start;
511
512 Web server embedding
513 You can also use "one_tick" in Mojo::IOLoop to embed the built-in web
514 server Mojo::Server::Daemon into alien environments like foreign event
515 loops that for some reason can't just be integrated with a new reactor
516 backend.
517
518 use Mojolicious::Lite;
519 use Mojo::IOLoop;
520 use Mojo::Server::Daemon;
521
522 # Normal action
523 get '/' => {text => 'Hello World!'};
524
525 # Connect application with web server and start accepting connections
526 my $daemon
527 = Mojo::Server::Daemon->new(app => app, listen => ['http://*:8080']);
528 $daemon->start;
529
530 # Call "one_tick" repeatedly from the alien environment
531 Mojo::IOLoop->one_tick while 1;
532
534 The real-time web is a collection of technologies that include Comet
535 (long polling), EventSource and WebSockets, which allow content to be
536 pushed to consumers with long-lived connections as soon as it is
537 generated, instead of relying on the more traditional pull model. All
538 built-in web servers use non-blocking I/O and are based on the
539 Mojo::IOLoop event loop, which provides many very powerful features
540 that allow real-time web applications to scale up to thousands of
541 concurrent client connections.
542
543 Backend web services
544 Since Mojo::UserAgent is also based on the Mojo::IOLoop event loop, it
545 won't block the built-in web servers when used non-blocking, even for
546 high latency backend web services.
547
548 use Mojolicious::Lite;
549
550 # Search MetaCPAN for "mojolicious"
551 get '/' => sub {
552 my $c = shift;
553 $c->ua->get('fastapi.metacpan.org/v1/module/_search?q=mojolicious' => sub {
554 my ($ua, $tx) = @_;
555 $c->render('metacpan', hits => $tx->result->json->{hits}{hits});
556 });
557 };
558
559 app->start;
560 __DATA__
561
562 @@ metacpan.html.ep
563 <!DOCTYPE html>
564 <html>
565 <head><title>MetaCPAN results for "mojolicious"</title></head>
566 <body>
567 % for my $hit (@$hits) {
568 <p><%= $hit->{_source}{release} %></p>
569 % }
570 </body>
571 </html>
572
573 The callback passed to "get" in Mojo::UserAgent will be executed once
574 the request to the backend web service has been finished, this is
575 called continuation-passing style.
576
577 Synchronizing non-blocking operations
578 Multiple non-blocking operations, such as concurrent requests, can be
579 easily synchronized with promises and "all" in Mojo::Promise. You
580 create Mojo::Promise objects manually or use methods like "get_p" in
581 Mojo::UserAgent that create them for you.
582
583 use Mojolicious::Lite;
584 use Mojo::Promise;
585 use Mojo::URL;
586
587 # Search MetaCPAN for "mojo" and "minion"
588 get '/' => sub {
589 my $c = shift;
590
591 # Create two promises
592 my $url = Mojo::URL->new('fastapi.metacpan.org/v1/module/_search');
593 my $mojo = $c->ua->get_p($url->clone->query({q => 'mojo'}));
594 my $minion = $c->ua->get_p($url->clone->query({q => 'minion'}));
595
596 # Render a response once both promises have been resolved
597 Mojo::Promise->all($mojo, $minion)->then(sub {
598 my ($mojo, $minion) = @_;
599 $c->render(json => {
600 mojo => $mojo->[0]->result->json('/hits/hits/0/_source/release'),
601 minion => $minion->[0]->result->json('/hits/hits/0/_source/release')
602 });
603 })->catch(sub {
604 my $err = shift;
605 $c->reply->exception($err);
606 })->wait;
607 };
608
609 app->start;
610
611 To create promises manually you just wrap your continuation-passing
612 style APIs in functions that return promises. Here's an example for how
613 "get_p" in Mojo::UserAgent works internally.
614
615 use Mojo::UserAgent;
616 use Mojo::Promise;
617
618 # Wrap a user agent method with a promise
619 my $ua = Mojo::UserAgent->new;
620 sub get_p {
621 my $promise = Mojo::Promise->new;
622 $ua->get(@_ => sub {
623 my ($ua, $tx) = @_;
624 my $err = $tx->error;
625 $promise->resolve($tx) if !$err || $err->{code};
626 $promise->reject($err->{message});
627 });
628 return $promise;
629 }
630
631 # Use our new promise generating function
632 get_p('https://mojolicious.org')->then(sub {
633 my $tx = shift;
634 say $tx->result->dom->at('title')->text;
635 })->wait;
636
637 Promises have three states, they start out as "pending" and you call
638 "resolve" in Mojo::Promise to transition them to "fulfilled", or
639 "reject" in Mojo::Promise to transition them to "rejected".
640
641 Timers
642 Timers, another primary feature of the event loop, are created with
643 "timer" in Mojo::IOLoop and can, for example, be used to delay
644 rendering of a response, and unlike "sleep", won't block any other
645 requests that might be processed concurrently.
646
647 use Mojolicious::Lite;
648 use Mojo::IOLoop;
649
650 # Wait 3 seconds before rendering a response
651 get '/' => sub {
652 my $c = shift;
653 Mojo::IOLoop->timer(3 => sub {
654 $c->render(text => 'Delayed by 3 seconds!');
655 });
656 };
657
658 app->start;
659
660 Recurring timers created with "recurring" in Mojo::IOLoop are slightly
661 more powerful, but need to be stopped manually, or they would just keep
662 getting emitted.
663
664 use Mojolicious::Lite;
665 use Mojo::IOLoop;
666
667 # Count to 5 in 1 second steps
668 get '/' => sub {
669 my $c = shift;
670
671 # Start recurring timer
672 my $i = 1;
673 my $id = Mojo::IOLoop->recurring(1 => sub {
674 $c->write_chunk($i);
675 $c->finish if $i++ == 5;
676 });
677
678 # Stop recurring timer
679 $c->on(finish => sub { Mojo::IOLoop->remove($id) });
680 };
681
682 app->start;
683
684 Timers are not tied to a specific request or connection, and can even
685 be created at startup time.
686
687 use Mojolicious::Lite;
688 use Mojo::IOLoop;
689
690 # Check title in the background every 10 seconds
691 my $title = 'Got no title yet.';
692 Mojo::IOLoop->recurring(10 => sub {
693 app->ua->get('https://mojolicious.org' => sub {
694 my ($ua, $tx) = @_;
695 $title = $tx->result->dom->at('title')->text;
696 });
697 });
698
699 # Show current title
700 get '/' => sub {
701 my $c = shift;
702 $c->render(json => {title => $title});
703 };
704
705 app->start;
706
707 Just remember that all these non-blocking operations are processed
708 cooperatively, so your callbacks shouldn't block for too long.
709
710 Subprocesses
711 You can also use subprocesses, created with "subprocess" in
712 Mojo::IOLoop, to perform computationally expensive operations without
713 blocking the event loop.
714
715 use Mojolicious::Lite;
716 use Mojo::IOLoop;
717
718 # Operation that would block the event loop for 5 seconds
719 get '/' => sub {
720 my $c = shift;
721 Mojo::IOLoop->subprocess(
722 sub {
723 my $subprocess = shift;
724 sleep 5;
725 return '♥', 'Mojolicious';
726 },
727 sub {
728 my ($subprocess, $err, @results) = @_;
729 $c->reply->exception($err) and return if $err;
730 $c->render(text => "I $results[0] $results[1]!");
731 }
732 );
733 };
734
735 app->start;
736
737 The first callback will be executed in a child process, without
738 blocking the event loop of the parent process. The results of the first
739 callback will then be shared between both processes, and the second
740 callback executed in the parent process.
741
742 Exceptions in non-blocking operations
743 Since timers and other non-blocking operations are running solely in
744 the event loop, outside of the application, exceptions that get thrown
745 in callbacks can't get caught and handled automatically. But you can
746 handle them manually by subscribing to the event "error" in
747 Mojo::Reactor or catching them inside the callback.
748
749 use Mojolicious::Lite;
750 use Mojo::IOLoop;
751
752 # Forward error messages to the application log
753 Mojo::IOLoop->singleton->reactor->on(error => sub {
754 my ($reactor, $err) = @_;
755 app->log->error($err);
756 });
757
758 # Exception only gets logged (and connection times out)
759 get '/connection_times_out' => sub {
760 my $c = shift;
761 Mojo::IOLoop->timer(2 => sub {
762 die 'This request will not be getting a response';
763 });
764 };
765
766 # Exception gets caught and handled
767 get '/catch_exception' => sub {
768 my $c = shift;
769 Mojo::IOLoop->timer(2 => sub {
770 eval { die 'This request will be getting a response' };
771 $c->reply->exception($@) if $@;
772 });
773 };
774
775 app->start;
776
777 A default subscriber that turns all errors into warnings will usually
778 be added by Mojo::IOLoop as a fallback.
779
780 Mojo::IOLoop->singleton->reactor->unsubscribe('error');
781
782 During development or for applications where crashing is simply
783 preferable, you can also make every exception that gets thrown in a
784 callback fatal by removing all of its subscribers.
785
786 WebSocket web service
787 The WebSocket protocol offers full bi-directional low-latency
788 communication channels between clients and servers. Receive messages
789 just by subscribing to events such as "message" in
790 Mojo::Transaction::WebSocket with "on" in Mojolicious::Controller and
791 return them with "send" in Mojolicious::Controller.
792
793 use Mojolicious::Lite;
794
795 # Template with browser-side code
796 get '/' => 'index';
797
798 # WebSocket echo service
799 websocket '/echo' => sub {
800 my $c = shift;
801
802 # Opened
803 $c->app->log->debug('WebSocket opened');
804
805 # Increase inactivity timeout for connection a bit
806 $c->inactivity_timeout(300);
807
808 # Incoming message
809 $c->on(message => sub {
810 my ($c, $msg) = @_;
811 $c->send("echo: $msg");
812 });
813
814 # Closed
815 $c->on(finish => sub {
816 my ($c, $code, $reason) = @_;
817 $c->app->log->debug("WebSocket closed with status $code");
818 });
819 };
820
821 app->start;
822 __DATA__
823
824 @@ index.html.ep
825 <!DOCTYPE html>
826 <html>
827 <head><title>Echo</title></head>
828 <body>
829 <script>
830 var ws = new WebSocket('<%= url_for('echo')->to_abs %>');
831
832 // Incoming messages
833 ws.onmessage = function (event) {
834 document.body.innerHTML += event.data + '<br/>';
835 };
836
837 // Outgoing messages
838 ws.onopen = function (event) {
839 window.setInterval(function () { ws.send('Hello Mojo!') }, 1000);
840 };
841 </script>
842 </body>
843 </html>
844
845 The event "finish" in Mojo::Transaction::WebSocket will be emitted
846 right after the WebSocket connection has been closed.
847
848 $c->tx->with_compression;
849
850 You can activate "permessage-deflate" compression with
851 "with_compression" in Mojo::Transaction::WebSocket, this can result in
852 much better performance, but also increases memory usage by up to
853 300KiB per connection.
854
855 my $proto = $c->tx->with_protocols('v2.proto', 'v1.proto');
856
857 You can also use "with_protocols" in Mojo::Transaction::WebSocket to
858 negotiate a subprotocol.
859
860 EventSource web service
861 EventSource is a special form of long polling where you can use "write"
862 in Mojolicious::Controller to directly send DOM events from servers to
863 clients. It is uni-directional, that means you will have to use Ajax
864 requests for sending data from clients to servers, the advantage
865 however is low infrastructure requirements, since it reuses the HTTP
866 protocol for transport.
867
868 use Mojolicious::Lite;
869
870 # Template with browser-side code
871 get '/' => 'index';
872
873 # EventSource for log messages
874 get '/events' => sub {
875 my $c = shift;
876
877 # Increase inactivity timeout for connection a bit
878 $c->inactivity_timeout(300);
879
880 # Change content type and finalize response headers
881 $c->res->headers->content_type('text/event-stream');
882 $c->write;
883
884 # Subscribe to "message" event and forward "log" events to browser
885 my $cb = $c->app->log->on(message => sub {
886 my ($log, $level, @lines) = @_;
887 $c->write("event:log\ndata: [$level] @lines\n\n");
888 });
889
890 # Unsubscribe from "message" event again once we are done
891 $c->on(finish => sub {
892 my $c = shift;
893 $c->app->log->unsubscribe(message => $cb);
894 });
895 };
896
897 app->start;
898 __DATA__
899
900 @@ index.html.ep
901 <!DOCTYPE html>
902 <html>
903 <head><title>LiveLog</title></head>
904 <body>
905 <script>
906 var events = new EventSource('<%= url_for 'events' %>');
907
908 // Subscribe to "log" event
909 events.addEventListener('log', function (event) {
910 document.body.innerHTML += event.data + '<br/>';
911 }, false);
912 </script>
913 </body>
914 </html>
915
916 The event "message" in Mojo::Log will be emitted for every new log
917 message and the event "finish" in Mojo::Transaction right after the
918 transaction has been finished.
919
920 Streaming multipart uploads
921 Mojolicious contains a very sophisticated event system based on
922 Mojo::EventEmitter, with ready-to-use events on almost all layers, and
923 which can be combined to solve some of the hardest problems in web
924 development.
925
926 use Mojolicious::Lite;
927 use Scalar::Util 'weaken';
928
929 # Intercept multipart uploads and log each chunk received
930 hook after_build_tx => sub {
931 my $tx = shift;
932
933 # Subscribe to "upgrade" event to identify multipart uploads
934 weaken $tx;
935 $tx->req->content->on(upgrade => sub {
936 my ($single, $multi) = @_;
937 return unless $tx->req->url->path->contains('/upload');
938
939 # Subscribe to "part" event to find the right one
940 $multi->on(part => sub {
941 my ($multi, $single) = @_;
942
943 # Subscribe to "body" event of part to make sure we have all headers
944 $single->on(body => sub {
945 my $single = shift;
946
947 # Make sure we have the right part and replace "read" event
948 return unless $single->headers->content_disposition =~ /example/;
949 $single->unsubscribe('read')->on(read => sub {
950 my ($single, $bytes) = @_;
951
952 # Log size of every chunk we receive
953 app->log->debug(length($bytes) . ' bytes uploaded');
954 });
955 });
956 });
957 });
958 };
959
960 # Upload form in DATA section
961 get '/' => 'index';
962
963 # Streaming multipart upload
964 post '/upload' => {text => 'Upload was successful.'};
965
966 app->start;
967 __DATA__
968
969 @@ index.html.ep
970 <!DOCTYPE html>
971 <html>
972 <head><title>Streaming multipart upload</title></head>
973 <body>
974 %= form_for upload => (enctype => 'multipart/form-data') => begin
975 %= file_field 'example'
976 %= submit_button 'Upload'
977 % end
978 </body>
979 </html>
980
981 More event loops
982 Internally, the Mojo::IOLoop event loop can use multiple reactor
983 backends, EV for example, will be automatically used if possible. Which
984 in turn allows other event loops like AnyEvent to just work.
985
986 use Mojolicious::Lite;
987 use EV;
988 use AnyEvent;
989
990 # Wait 3 seconds before rendering a response
991 get '/' => sub {
992 my $c = shift;
993 my $w;
994 $w = AE::timer 3, 0, sub {
995 $c->render(text => 'Delayed by 3 seconds!');
996 undef $w;
997 };
998 };
999
1000 app->start;
1001
1002 Who actually controls the event loop backend is not important.
1003
1004 use Mojo::UserAgent;
1005 use EV;
1006 use AnyEvent;
1007
1008 # Search MetaCPAN for "mojolicious"
1009 my $cv = AE::cv;
1010 my $ua = Mojo::UserAgent->new;
1011 $ua->get('fastapi.metacpan.org/v1/module/_search?q=mojolicious' => sub {
1012 my ($ua, $tx) = @_;
1013 $cv->send($tx->result->json('/hits/hits/0/_source/release'));
1014 });
1015 say $cv->recv;
1016
1017 You could, for example, just embed the built-in web server into an
1018 AnyEvent application.
1019
1020 use Mojolicious::Lite;
1021 use Mojo::Server::Daemon;
1022 use EV;
1023 use AnyEvent;
1024
1025 # Normal action
1026 get '/' => {text => 'Hello World!'};
1027
1028 # Connect application with web server and start accepting connections
1029 my $daemon
1030 = Mojo::Server::Daemon->new(app => app, listen => ['http://*:8080']);
1031 $daemon->start;
1032
1033 # Let AnyEvent take control
1034 AE::cv->recv;
1035
1037 When we say Mojolicious is a web framework we actually mean it, with
1038 Mojo::UserAgent there's a full featured HTTP and WebSocket user agent
1039 built right in.
1040
1041 REST web services
1042 Requests can be performed very comfortably with methods like "get" in
1043 Mojo::UserAgent, and always result in a Mojo::Transaction::HTTP object,
1044 which has many useful attributes and methods. You can check for
1045 connection errors with "result" in Mojo::Transaction, or access HTTP
1046 request and response information directly through "req" in
1047 Mojo::Transaction and "res" in Mojo::Transaction.
1048
1049 use Mojo::UserAgent;
1050
1051 # Request a resource and make sure there were no connection errors
1052 my $ua = Mojo::UserAgent->new;
1053 my $tx = $ua->get('mojolicious.org/perldoc/Mojo' => {Accept => 'text/plain'});
1054 my $res = $tx->result;
1055
1056 # Decide what to do with its representation
1057 if ($res->is_success) { say $res->body }
1058 elsif ($res->is_error) { say $res->message }
1059 elsif ($res->code == 301) { say $res->headers->location }
1060 else { say 'Whatever...' }
1061
1062 While methods like "is_success" in Mojo::Message::Response and
1063 "is_error" in Mojo::Message::Response serve as building blocks for more
1064 sophisticated REST clients.
1065
1066 Web scraping
1067 Scraping information from websites has never been this much fun before.
1068 The built-in HTML/XML parser Mojo::DOM is accessible through "dom" in
1069 Mojo::Message and supports all CSS selectors that make sense for a
1070 standalone parser, it can be a very powerful tool especially for
1071 testing web application.
1072
1073 use Mojo::UserAgent;
1074
1075 # Fetch website
1076 my $ua = Mojo::UserAgent->new;
1077 my $res = $ua->get('mojolicious.org/perldoc')->result;
1078
1079 # Extract title
1080 say 'Title: ', $res->dom->at('head > title')->text;
1081
1082 # Extract headings
1083 $res->dom('h1, h2, h3')->each(sub { say 'Heading: ', shift->all_text });
1084
1085 # Visit all nodes recursively to extract more than just text
1086 for my $n ($res->dom->descendant_nodes->each) {
1087
1088 # Text or CDATA node
1089 print $n->content if $n->type eq 'text' || $n->type eq 'cdata';
1090
1091 # Also include alternate text for images
1092 print $n->{alt} if $n->type eq 'tag' && $n->tag eq 'img';
1093 }
1094
1095 For a full list of available CSS selectors see "SELECTORS" in
1096 Mojo::DOM::CSS.
1097
1098 JSON web services
1099 Most web services these days are based on the JSON data-interchange
1100 format. That's why Mojolicious comes with the possibly fastest pure-
1101 Perl implementation Mojo::JSON built right in, which is accessible
1102 through "json" in Mojo::Message.
1103
1104 use Mojo::UserAgent;
1105 use Mojo::URL;
1106
1107 # Fresh user agent
1108 my $ua = Mojo::UserAgent->new;
1109
1110 # Search MetaCPAN for "mojolicious" and list latest releases
1111 my $url = Mojo::URL->new('http://fastapi.metacpan.org/v1/release/_search');
1112 $url->query({q => 'mojolicious', sort => 'date:desc'});
1113 for my $hit (@{$ua->get($url)->result->json->{hits}{hits}}) {
1114 say "$hit->{_source}{name} ($hit->{_source}{author})";
1115 }
1116
1117 Basic authentication
1118 You can just add username and password to the URL, an "Authorization"
1119 header will be automatically generated.
1120
1121 use Mojo::UserAgent;
1122
1123 my $ua = Mojo::UserAgent->new;
1124 say $ua->get('https://sri:secret@example.com/hideout')->result->body;
1125
1126 Decorating follow-up requests
1127 Mojo::UserAgent can automatically follow redirects, the event "start"
1128 in Mojo::UserAgent allows you direct access to each transaction right
1129 after they have been initialized and before a connection gets
1130 associated with them.
1131
1132 use Mojo::UserAgent;
1133
1134 # User agent following up to 10 redirects
1135 my $ua = Mojo::UserAgent->new(max_redirects => 10);
1136
1137 # Add a witty header to every request
1138 $ua->on(start => sub {
1139 my ($ua, $tx) = @_;
1140 $tx->req->headers->header('X-Bender' => 'Bite my shiny metal ass!');
1141 say 'Request: ', $tx->req->url->clone->to_abs;
1142 });
1143
1144 # Request that will most likely get redirected
1145 say 'Title: ', $ua->get('google.com')->result->dom->at('head > title')->text;
1146
1147 This even works for proxy "CONNECT" requests.
1148
1149 Content generators
1150 Content generators can be registered with "add_generator" in
1151 Mojo::UserAgent::Transactor to generate the same type of content
1152 repeatedly for multiple requests.
1153
1154 use Mojo::UserAgent;
1155 use Mojo::Asset::File;
1156
1157 # Add "stream" generator
1158 my $ua = Mojo::UserAgent->new;
1159 $ua->transactor->add_generator(stream => sub {
1160 my ($transactor, $tx, $path) = @_;
1161 $tx->req->content->asset(Mojo::Asset::File->new(path => $path));
1162 });
1163
1164 # Send multiple files streaming via PUT and POST
1165 $ua->put('http://example.com/upload' => stream => '/home/sri/mojo.png');
1166 $ua->post('http://example.com/upload' => stream => '/home/sri/minion.png');
1167
1168 The "json", "form" and "multipart" content generators are always
1169 available.
1170
1171 use Mojo::UserAgent;
1172
1173 # Send "application/json" content via PATCH
1174 my $ua = Mojo::UserAgent->new;
1175 my $tx = $ua->patch('http://api.example.com' => json => {foo => 'bar'});
1176
1177 # Send query parameters via GET
1178 my $tx2 = $ua->get('search.example.com' => form => {q => 'test'});
1179
1180 # Send "application/x-www-form-urlencoded" content via POST
1181 my $tx3 = $ua->post('http://search.example.com' => form => {q => 'test'});
1182
1183 # Send "multipart/form-data" content via PUT
1184 my $tx4 = $ua->put(
1185 'upload.example.com' => form => {test => {content => 'Hello World!'}});
1186
1187 # Send custom multipart content via PUT
1188 my $tx5 = $ua->put('api.example.com' => multipart => ['Hello', 'World!']);
1189
1190 For more information about available content generators see also "tx"
1191 in Mojo::UserAgent::Transactor.
1192
1193 Large file downloads
1194 When downloading large files with Mojo::UserAgent you don't have to
1195 worry about memory usage at all, because it will automatically stream
1196 everything above 250KiB into a temporary file, which can then be moved
1197 into a permanent file with "save_to" in Mojo::Message.
1198
1199 use Mojo::UserAgent;
1200
1201 # Fetch the latest Mojolicious tarball
1202 my $ua = Mojo::UserAgent->new(max_redirects => 5);
1203 my $tx = $ua->get('https://www.github.com/mojolicious/mojo/tarball/master');
1204 $tx->result->save_to('mojo.tar.gz');
1205
1206 To protect you from excessively large files there is also a limit of
1207 2GiB by default, which you can tweak with the attribute
1208 "max_response_size" in Mojo::UserAgent.
1209
1210 # Increase limit to 10GiB
1211 $ua->max_response_size(10737418240);
1212
1213 Large file upload
1214 Uploading a large file is even easier.
1215
1216 use Mojo::UserAgent;
1217
1218 # Upload file via POST and "multipart/form-data"
1219 my $ua = Mojo::UserAgent->new;
1220 $ua->post('example.com/upload' =>
1221 form => {image => {file => '/home/sri/hello.png'}});
1222
1223 And once again you don't have to worry about memory usage, all data
1224 will be streamed directly from the file.
1225
1226 Streaming response
1227 Receiving a streaming response can be really tricky in most HTTP
1228 clients, but Mojo::UserAgent makes it actually easy.
1229
1230 use Mojo::UserAgent;
1231
1232 # Accept responses of indefinite size
1233 my $ua = Mojo::UserAgent->new(max_response_size => 0);
1234
1235 # Build a normal transaction
1236 my $tx = $ua->build_tx(GET => 'http://example.com');
1237
1238 # Replace "read" events to disable default content parser
1239 $tx->res->content->unsubscribe('read')->on(read => sub {
1240 my ($content, $bytes) = @_;
1241 say "Streaming: $bytes";
1242 });
1243
1244 # Process transaction
1245 $tx = $ua->start($tx);
1246
1247 The event "read" in Mojo::Content will be emitted for every chunk of
1248 data that is received, even chunked transfer encoding and gzip content
1249 encoding will be handled transparently if necessary.
1250
1251 Streaming request
1252 Sending a streaming request is almost just as easy.
1253
1254 use Mojo::UserAgent;
1255
1256 # Build a normal transaction
1257 my $ua = Mojo::UserAgent->new;
1258 my $tx = $ua->build_tx(GET => 'http://example.com');
1259
1260 # Prepare body
1261 my $body = 'Hello World!';
1262 $tx->req->headers->content_length(length $body);
1263
1264 # Start writing directly with a drain callback
1265 my $drain;
1266 $drain = sub {
1267 my $content = shift;
1268 my $chunk = substr $body, 0, 1, '';
1269 $drain = undef unless length $body;
1270 $content->write($chunk, $drain);
1271 };
1272 $tx->req->content->$drain;
1273
1274 # Process transaction
1275 $tx = $ua->start($tx);
1276
1277 The drain callback passed to "write" in Mojo::Content will be executed
1278 whenever the entire previous chunk of data has actually been written.
1279
1280 Non-blocking
1281 Mojo::UserAgent has been designed from the ground up to be non-
1282 blocking, the whole blocking API is just a simple convenience wrapper.
1283 Especially for high latency tasks like web crawling this can be
1284 extremely useful, because you can keep many concurrent connections
1285 active at the same time.
1286
1287 use Mojo::UserAgent;
1288 use Mojo::IOLoop;
1289
1290 # Concurrent non-blocking requests
1291 my $ua = Mojo::UserAgent->new;
1292 $ua->get('https://metacpan.org/search?q=mojo' => sub {
1293 my ($ua, $mojo) = @_;
1294 say $mojo->result->dom->at('title')->text;
1295 });
1296 $ua->get('https://metacpan.org/search?q=minion' => sub {
1297 my ($ua, $minion) = @_;
1298 say $minion->result->dom->at('title')->text;
1299 });
1300
1301 # Start event loop if necessary
1302 Mojo::IOLoop->start unless Mojo::IOLoop->is_running;
1303
1304 But don't try to open too many connections to one server at the same
1305 time, it might get overwhelmed. Better use a queue to process requests
1306 in smaller batches.
1307
1308 use Mojo::UserAgent;
1309 use Mojo::IOLoop;
1310
1311 my @urls = (
1312 'mojolicious.org/perldoc/Mojo/DOM', 'mojolicious.org/perldoc/Mojo',
1313 'mojolicious.org/perldoc/Mojo/File', 'mojolicious.org/perldoc/Mojo/URL'
1314 );
1315
1316 # User agent with a custom name, following up to 5 redirects
1317 my $ua = Mojo::UserAgent->new(max_redirects => 5);
1318 $ua->transactor->name('MyParallelCrawler 1.0');
1319
1320 # Use a delay to keep the event loop running until we are done
1321 my $delay = Mojo::IOLoop->delay;
1322 my $fetch;
1323 $fetch = sub {
1324
1325 # Stop if there are no more URLs
1326 return unless my $url = shift @urls;
1327
1328 # Fetch the next title
1329 my $end = $delay->begin;
1330 $ua->get($url => sub {
1331 my ($ua, $tx) = @_;
1332 say "$url: ", $tx->result->dom->at('title')->text;
1333
1334 # Next request
1335 $fetch->();
1336 $end->();
1337 });
1338 };
1339
1340 # Process two requests at a time
1341 $fetch->() for 1 .. 2;
1342 $delay->wait;
1343
1344 It is also strongly recommended to respect every sites "robots.txt"
1345 file as well as terms of service, and to wait a little before reopening
1346 connections to the same host, or the operators might be forced to block
1347 your access.
1348
1349 Concurrent blocking requests
1350 You might have seen "wait" in Mojo::Promise already in some examples
1351 above. It is used to make non-blocking operations portable, allowing
1352 them to work inside an already running event loop or start one on
1353 demand.
1354
1355 use Mojo::UserAgent;
1356 use Mojo::Promise;
1357
1358 # Synchronize non-blocking requests with promises
1359 my $ua = Mojo::UserAgent->new;
1360 my $mojo = $ua->get_p('https://metacpan.org/search?q=mojo');
1361 my $minion = $ua->get_p('https://metacpan.org/search?q=minion');
1362 Mojo::Promise->all($mojo, $minion)->then(sub {
1363 my ($mojo, $minion) = @_;
1364 say $mojo->[0]->result->dom->at('title')->text;
1365 say $minion->[0]->result->dom->at('title')->text;
1366 })->wait;
1367
1368 WebSockets
1369 WebSockets are not just for the server-side, you can use "websocket_p"
1370 in Mojo::UserAgent to open new connections, which are always non-
1371 blocking. The WebSocket handshake uses HTTP, and is a normal "GET"
1372 request with a few additional headers. It can even contain cookies, and
1373 is followed by a 101 response from the server, notifying our user agent
1374 that the connection has been established and it can start using the bi-
1375 directional WebSocket protocol.
1376
1377 use Mojo::UserAgent;
1378 use Mojo::Promise;
1379
1380 # Open WebSocket to echo service
1381 my $ua = Mojo::UserAgent->new;
1382 $ua->websocket_p('ws://echo.websocket.org')->then(sub {
1383 my $tx = shift;
1384
1385 # Prepare a followup promise so we can wait for messages
1386 my $promise = Mojo::Promise->new;
1387
1388 # Wait for WebSocket to be closed
1389 $tx->on(finish => sub {
1390 my ($tx, $code, $reason) = @_;
1391 say "WebSocket closed with status $code.";
1392 $promise->resolve;
1393 });
1394
1395 # Close WebSocket after receiving one message
1396 $tx->on(message => sub {
1397 my ($tx, $msg) = @_;
1398 say "WebSocket message: $msg";
1399 $tx->finish;
1400 });
1401
1402 # Send a message to the server
1403 $tx->send('Hi!');
1404
1405 # Insert a new promise into the promise chain
1406 return $promise;
1407 })->catch(sub {
1408 my $err = shift;
1409
1410 # Handle failed WebSocket handshakes and other exceptions
1411 warn "WebSocket error: $err";
1412 })->wait;
1413
1414 UNIX domain sockets
1415 Not just TCP/IP sockets are supported, but also UNIX domain sockets,
1416 which can have significant security and performance benefits when used
1417 for inter-process communication. Instead of "http://" and "ws://" you
1418 can use the "http+unix://" and "ws+unix://" schemes, and pass along a
1419 percent encoded path ("/" becomes %2F) instead of a hostname.
1420
1421 use Mojo::UserAgent;
1422 use Mojo::Promise;
1423
1424 # GET request via UNIX domain socket "/tmp/foo.sock"
1425 my $ua = Mojo::UserAgent->new;
1426 say $ua->get('http+unix://%2Ftmp%2Ffoo.sock/index.html')->result->body;
1427
1428 # GET request with HOST header via UNIX domain socket "/tmp/bar.sock"
1429 my $tx = $ua->get('http+unix://%2Ftmp%2Fbar.sock' => {Host => 'example.com'});
1430 say $tx->result->body;
1431
1432 # WebSocket connection via UNIX domain socket "/tmp/baz.sock"
1433 $ua->websocket_p('ws+unix://%2Ftmp%2Fbaz.sock/echo')->then(sub {
1434 my $tx = shift;
1435
1436 my $promise = Mojo::Promise->new;
1437 $tx->on(finish => sub { $promise->resolve });
1438
1439 $tx->on(message => sub {
1440 my ($tx, $msg) = @_;
1441 say "WebSocket message: $msg";
1442 $tx->finish;
1443 });
1444 $tx->send('Hi!');
1445
1446 return $promise;
1447 })->catch(sub {
1448 my $err = shift;
1449 warn "WebSocket error: $err";
1450 })->wait;
1451
1452 You can set the "Host" header manually to pass along a hostname.
1453
1454 Command line
1455 Don't you hate checking huge HTML files from the command line? Thanks
1456 to the command Mojolicious::Command::get that is about to change. You
1457 can just pick the parts that actually matter with the CSS selectors
1458 from Mojo::DOM and JSON Pointers from Mojo::JSON::Pointer.
1459
1460 $ mojo get https://mojolicious.org 'head > title'
1461
1462 How about a list of all id attributes?
1463
1464 $ mojo get https://mojolicious.org '*' attr id
1465
1466 Or the text content of all heading tags?
1467
1468 $ mojo get https://mojolicious.org 'h1, h2, h3' text
1469
1470 Maybe just the text of the third heading?
1471
1472 $ mojo get https://mojolicious.org 'h1, h2, h3' 3 text
1473
1474 You can also extract all text from nested child elements.
1475
1476 $ mojo get https://mojolicious.org '#mojobar' all
1477
1478 The request can be customized as well.
1479
1480 $ mojo get -M POST -H 'X-Bender: Bite my shiny metal ass!' http://google.com
1481
1482 Store response data by redirecting "STDOUT".
1483
1484 $ mojo get mojolicious.org > example.html
1485
1486 Pass request data by redirecting "STDIN".
1487
1488 $ mojo get -M PUT mojolicious.org < example.html
1489
1490 Or use the output of another program.
1491
1492 $ echo 'Hello World' | mojo get -M PUT https://mojolicious.org
1493
1494 Submit forms as "application/x-www-form-urlencoded" content.
1495
1496 $ mojo get -M POST -f 'q=Mojo' -f 'size=5' https://metacpan.org/search
1497
1498 And upload files as "multipart/form-data" content.
1499
1500 $ mojo get -M POST -f 'upload=@example.html' mojolicious.org
1501
1502 You can follow redirects and view the headers for all messages.
1503
1504 $ mojo get -r -v http://google.com 'head > title'
1505
1506 Extract just the information you really need from JSON data structures.
1507
1508 $ mojo get https://fastapi.metacpan.org/v1/author/SRI /name
1509
1510 This can be an invaluable tool for testing your applications.
1511
1512 $ ./myapp.pl get /welcome 'head > title'
1513
1514 One-liners
1515 For quick hacks and especially testing, ojo one-liners are also a great
1516 choice.
1517
1518 $ perl -Mojo -E 'say g("mojolicious.org")->dom->at("title")->text'
1519
1521 Fun Mojolicious application hacks for all occasions.
1522
1523 Basic authentication
1524 Basic authentication data will be automatically extracted from the
1525 "Authorization" header.
1526
1527 use Mojolicious::Lite;
1528 use Mojo::Util 'secure_compare';
1529
1530 get '/' => sub {
1531 my $c = shift;
1532
1533 # Check for username "Bender" and password "rocks"
1534 return $c->render(text => 'Hello Bender!')
1535 if secure_compare $c->req->url->to_abs->userinfo, 'Bender:rocks';
1536
1537 # Require authentication
1538 $c->res->headers->www_authenticate('Basic');
1539 $c->render(text => 'Authentication required!', status => 401);
1540 };
1541
1542 app->start;
1543
1544 This can be combined with TLS for a secure authentication mechanism.
1545
1546 $ ./myapp.pl daemon -l 'https://*:3000?cert=./server.crt&key=./server.key'
1547
1548 Adding a configuration file
1549 Adding a configuration file to your application is as easy as adding a
1550 file to its home directory and loading the plugin
1551 Mojolicious::Plugin::Config. The default name is based on the value of
1552 "moniker" in Mojolicious ("myapp"), appended with a ".conf" extension
1553 ("myapp.conf").
1554
1555 $ mkdir myapp
1556 $ cd myapp
1557 $ touch myapp.pl
1558 $ chmod 744 myapp.pl
1559 $ echo '{name => "my Mojolicious application"};' > myapp.conf
1560
1561 Configuration files themselves are just Perl scripts that return a hash
1562 reference with configuration settings of your choice. All those
1563 settings are then available through the method "config" in Mojolicious
1564 and the helper "config" in Mojolicious::Plugin::DefaultHelpers.
1565
1566 use Mojolicious::Lite;
1567
1568 plugin 'Config';
1569
1570 my $name = app->config('name');
1571 app->log->debug("Welcome to $name");
1572
1573 get '/' => 'with_config';
1574
1575 app->start;
1576 __DATA__
1577 @@ with_config.html.ep
1578 <!DOCTYPE html>
1579 <html>
1580 <head><title><%= config 'name' %></title></head>
1581 <body>Welcome to <%= config 'name' %></body>
1582 </html>
1583
1584 Alternatively you can also use configuration files in the JSON format
1585 with Mojolicious::Plugin::JSONConfig.
1586
1587 Adding a plugin to your application
1588 To organize your code better and to prevent helpers from cluttering
1589 your application, you can use application specific plugins.
1590
1591 $ mkdir -p lib/MyApp/Plugin
1592 $ touch lib/MyApp/Plugin/MyHelpers.pm
1593
1594 They work just like normal plugins and are also subclasses of
1595 Mojolicious::Plugin. Nested helpers with a prefix based on the plugin
1596 name are an easy way to avoid conflicts.
1597
1598 package MyApp::Plugin::MyHelpers;
1599 use Mojo::Base 'Mojolicious::Plugin';
1600
1601 sub register {
1602 my ($self, $app) = @_;
1603 $app->helper('my_helpers.render_with_header' => sub {
1604 my ($c, @args) = @_;
1605 $c->res->headers->header('X-Mojo' => 'I <3 Mojolicious!');
1606 $c->render(@args);
1607 });
1608 }
1609
1610 1;
1611
1612 You can have as many application specific plugins as you like, the only
1613 difference to normal plugins is that you load them using their full
1614 class name.
1615
1616 use Mojolicious::Lite;
1617
1618 use lib 'lib';
1619
1620 plugin 'MyApp::Plugin::MyHelpers';
1621
1622 get '/' => sub {
1623 my $c = shift;
1624 $c->my_helpers->render_with_header(text => 'I ♥ Mojolicious!');
1625 };
1626
1627 app->start;
1628
1629 Of course these plugins can contain more than just helpers, take a look
1630 at "PLUGINS" in Mojolicious::Plugins for a few ideas.
1631
1632 Adding commands to Mojolicious
1633 By now you've probably used many of the built-in commands described in
1634 Mojolicious::Commands, but did you know that you can just add new ones
1635 and that they will be picked up automatically by the command line
1636 interface if they are placed in a directory from @INC?
1637
1638 package Mojolicious::Command::spy;
1639 use Mojo::Base 'Mojolicious::Command';
1640
1641 has description => 'Spy on application';
1642 has usage => "Usage: APPLICATION spy [TARGET]\n";
1643
1644 sub run {
1645 my ($self, @args) = @_;
1646
1647 # Leak secret passphrases
1648 if ($args[0] eq 'secrets') { say for @{$self->app->secrets} }
1649
1650 # Leak mode
1651 elsif ($args[0] eq 'mode') { say $self->app->mode }
1652 }
1653
1654 1;
1655
1656 Command line arguments are passed right through and there are many
1657 useful attributes and methods in Mojolicious::Command that you can use
1658 or overload.
1659
1660 $ mojo spy secrets
1661 HelloWorld
1662
1663 $ ./script/myapp spy secrets
1664 secr3t
1665
1666 And to make your commands application specific, just add a custom
1667 namespace to "namespaces" in Mojolicious::Commands and use a class name
1668 like "MyApp::Command::spy" instead of "Mojolicious::Command::spy".
1669
1670 # Application
1671 package MyApp;
1672 use Mojo::Base 'Mojolicious';
1673
1674 sub startup {
1675 my $self = shift;
1676
1677 # Add another namespace to load commands from
1678 push @{$self->commands->namespaces}, 'MyApp::Command';
1679 }
1680
1681 1;
1682
1683 The options "-h"/"--help", "--home" and "-m"/"--mode" are handled
1684 automatically by Mojolicious::Commands and are shared by all commands.
1685
1686 $ ./script/myapp spy -m production mode
1687 production
1688
1689 For a full list of shared options see "SYNOPSIS" in
1690 Mojolicious::Commands.
1691
1692 Running code against your application
1693 Ever thought about running a quick one-liner against your Mojolicious
1694 application to test something? Thanks to the command
1695 Mojolicious::Command::eval you can do just that, the application object
1696 itself can be accessed via "app".
1697
1698 $ mojo generate lite_app myapp.pl
1699 $ ./myapp.pl eval 'say for @{app->static->paths}'
1700 $ ./myapp.pl eval 'say for sort keys %{app->renderer->helpers}'
1701
1702 The "verbose" options will automatically print the return value or
1703 returned data structure to "STDOUT".
1704
1705 $ ./myapp.pl eval -v 'app->static->paths->[0]'
1706 $ ./myapp.pl eval -V 'app->static->paths'
1707
1708 Making your application installable
1709 Ever thought about releasing your Mojolicious application to CPAN? It's
1710 actually much easier than you might think.
1711
1712 $ mojo generate app MyApp
1713 $ cd my_app
1714 $ mv public lib/MyApp/
1715 $ mv templates lib/MyApp/
1716
1717 The trick is to move the "public" and "templates" directories so they
1718 can get automatically installed with the modules. Additionally author
1719 commands from the "Mojolicious::Command::Author" namespace are not
1720 usually wanted by an installed application so they can be excluded.
1721
1722 # Application
1723 package MyApp;
1724 use Mojo::Base 'Mojolicious';
1725
1726 use Mojo::File 'path';
1727 use Mojo::Home;
1728
1729 # Every CPAN module needs a version
1730 our $VERSION = '1.0';
1731
1732 sub startup {
1733 my $self = shift;
1734
1735 # Switch to installable home directory
1736 $self->home(Mojo::Home->new(path(__FILE__)->sibling('MyApp')));
1737
1738 # Switch to installable "public" directory
1739 $self->static->paths->[0] = $self->home->child('public');
1740
1741 # Switch to installable "templates" directory
1742 $self->renderer->paths->[0] = $self->home->child('templates');
1743
1744 # Exclude author commands
1745 $self->commands->namespaces(['Mojolicious::Commands']);
1746
1747 my $r = $self->routes;
1748 $r->get('/welcome')->to('example#welcome');
1749 }
1750
1751 1;
1752
1753 Finally there is just one small change to be made to the application
1754 script. The shebang line becomes the recommended "#!perl", which the
1755 toolchain can rewrite to the proper shebang during installation.
1756
1757 #!perl
1758
1759 use strict;
1760 use warnings;
1761
1762 use FindBin;
1763 BEGIN { unshift @INC, "$FindBin::Bin/../lib" }
1764 use Mojolicious::Commands;
1765
1766 # Start command line interface for application
1767 Mojolicious::Commands->start_app('MyApp');
1768
1769 That's really everything, now you can package your application like any
1770 other CPAN module.
1771
1772 $ ./script/my_app generate makefile
1773 $ perl Makefile.PL
1774 $ make test
1775 $ make manifest
1776 $ make dist
1777
1778 And if you have a PAUSE account (which can be requested at
1779 <http://pause.perl.org>) even upload it.
1780
1781 $ mojo cpanify -u USER -p PASS MyApp-0.01.tar.gz
1782
1783 Hello World
1784 If every byte matters this is the smallest "Hello World" application
1785 you can write with Mojolicious::Lite.
1786
1787 use Mojolicious::Lite;
1788 any {text => 'Hello World!'};
1789 app->start;
1790
1791 It works because all routes without a pattern default to "/" and
1792 automatic rendering kicks in even if no actual code gets executed by
1793 the router. The renderer just picks up the "text" value from the stash
1794 and generates a response.
1795
1796 Hello World one-liners
1797 The "Hello World" example above can get even a little bit shorter in an
1798 ojo one-liner.
1799
1800 $ perl -Mojo -E 'a({text => "Hello World!"})->start' daemon
1801
1802 And you can use all the commands from Mojolicious::Commands.
1803
1804 $ perl -Mojo -E 'a({text => "Hello World!"})->start' get -v /
1805
1807 You can continue with Mojolicious::Guides now or take a look at the
1808 Mojolicious wiki <http://github.com/mojolicious/mojo/wiki>, which
1809 contains a lot more documentation and examples by many different
1810 authors.
1811
1813 If you have any questions the documentation might not yet answer, don't
1814 hesitate to ask on the mailing list
1815 <http://groups.google.com/group/mojolicious> or the official IRC
1816 channel "#mojo" on "irc.freenode.net" (chat now!
1817 <https://kiwiirc.com/nextclient/#irc://irc.freenode.net/mojo?nick=guest-?>).
1818
1819
1820
1821perl v5.28.1 2018-11-01 Mojolicious::Guides::Cookbook(3)