source: main/trunk/greenstone2/perllib/cpan/Mojolicious/Guides/Cookbook.pod@ 32205

Last change on this file since 32205 was 32205, checked in by ak19, 6 years ago

First set of commits to do with implementing the new 'paged_html' output option of PDFPlugin that uses using xpdftools' new pdftohtml. So far tested only on Linux (64 bit), but things work there so I'm optimistically committing the changes since they work. 2. Committing the pre-built Linux binaries of XPDFtools for both 32 and 64 bit built by the XPDF group. 2. To use the correct bitness variant of xpdftools, setup.bash now exports the BITNESS env var, consulted by gsConvert.pl. 3. All the perl code changes to do with using xpdf tools' pdftohtml to generate paged_html and feed it in the desired form into GS(3): gsConvert.pl, PDFPlugin.pm and its parent ConvertBinaryPFile.pm have been modified to make it all work. xpdftools' pdftohtml generates a folder containing an html file and a screenshot for each page in a PDF (as well as an index.html linking to each page's html). However, we want a single html file that contains each individual 'page' html's content in a div, and need to do some further HTML style, attribute and structure modifications to massage the xpdftool output to what we want for GS. In order to parse and manipulate the HTML 'DOM' to do this, we're using the Mojo::DOM package that Dr Bainbridge found and which he's compiled up. Mojo::DOM is therefore also committed in this revision. Some further changes and some display fixes are required, but need to check with the others about that.

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