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