source: main/trunk/greenstone2/perllib/cpan/Mojo/UserAgent.pm@ 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: 33.5 KB
Line 
1package Mojo::UserAgent;
2use Mojo::Base 'Mojo::EventEmitter';
3
4# "Fry: Since when is the Internet about robbing people of their privacy?
5# Bender: August 6, 1991."
6use Mojo::IOLoop;
7use Mojo::IOLoop::Stream::HTTPClient;
8use Mojo::IOLoop::Stream::WebSocketClient;
9use Mojo::Promise;
10use Mojo::Util 'monkey_patch';
11use Mojo::UserAgent::CookieJar;
12use Mojo::UserAgent::Proxy;
13use Mojo::UserAgent::Server;
14use Mojo::UserAgent::Transactor;
15use Scalar::Util 'weaken';
16
17use constant DEBUG => $ENV{MOJO_CLIENT_DEBUG} || 0;
18
19has ca => sub { $ENV{MOJO_CA_FILE} };
20has cert => sub { $ENV{MOJO_CERT_FILE} };
21has connect_timeout => sub { $ENV{MOJO_CONNECT_TIMEOUT} || 10 };
22has cookie_jar => sub { Mojo::UserAgent::CookieJar->new };
23has inactivity_timeout => sub { $ENV{MOJO_INACTIVITY_TIMEOUT} // 20 };
24has insecure => sub { $ENV{MOJO_INSECURE} };
25has [qw(local_address max_response_size)];
26has ioloop => sub { Mojo::IOLoop->new };
27has key => sub { $ENV{MOJO_KEY_FILE} };
28has max_connections => 5;
29has max_redirects => sub { $ENV{MOJO_MAX_REDIRECTS} || 0 };
30has proxy => sub { Mojo::UserAgent::Proxy->new };
31has request_timeout => sub { $ENV{MOJO_REQUEST_TIMEOUT} // 0 };
32has server => sub { Mojo::UserAgent::Server->new(ioloop => shift->ioloop) };
33has transactor => sub { Mojo::UserAgent::Transactor->new };
34
35# Common HTTP methods
36for my $name (qw(DELETE GET HEAD OPTIONS PATCH POST PUT)) {
37 monkey_patch __PACKAGE__, lc $name, sub {
38 my ($self, $cb) = (shift, ref $_[-1] eq 'CODE' ? pop : undef);
39 return $self->start($self->build_tx($name, @_), $cb);
40 };
41 monkey_patch __PACKAGE__, lc($name) . '_p', sub {
42 my $self = shift;
43 return $self->start_p($self->build_tx($name, @_));
44 };
45}
46
47sub DESTROY { Mojo::Util::_global_destruction() or shift->_cleanup }
48
49sub build_tx { shift->transactor->tx(@_) }
50sub build_websocket_tx { shift->transactor->websocket(@_) }
51
52sub start {
53 my ($self, $tx, $cb) = @_;
54
55 # Fork-safety
56 $self->_cleanup->server->restart unless ($self->{pid} //= $$) eq $$;
57
58 # Non-blocking
59 if ($cb) {
60 warn "-- Non-blocking request (@{[_url($tx)]})\n" if DEBUG;
61 return $self->_start(Mojo::IOLoop->singleton, $tx, $cb);
62 }
63
64 # Blocking
65 warn "-- Blocking request (@{[_url($tx)]})\n" if DEBUG;
66 $self->_start($self->ioloop, $tx => sub { shift->ioloop->stop; $tx = shift });
67 $self->ioloop->start;
68
69 return $tx;
70}
71
72sub start_p {
73 my ($self, $tx) = @_;
74
75 my $promise = Mojo::Promise->new;
76 $self->start(
77 $tx => sub {
78 my ($self, $tx) = @_;
79 my $err = $tx->error;
80 return $promise->reject($err->{message}) if $err && !$err->{code};
81 return $promise->reject('WebSocket handshake failed')
82 if $tx->req->is_handshake && !$tx->is_websocket;
83 $promise->resolve($tx);
84 }
85 );
86
87 return $promise;
88}
89
90sub websocket {
91 my ($self, $cb) = (shift, pop);
92 $self->start($self->build_websocket_tx(@_), $cb);
93}
94
95sub websocket_p {
96 my $self = shift;
97 return $self->start_p($self->build_websocket_tx(@_));
98}
99
100sub _cleanup {
101 my $self = shift;
102 delete $self->{pid};
103 $self->_error($_, 'Premature connection close')
104 for keys %{$self->{connections} || {}};
105 return $self;
106}
107
108sub _connect {
109 my ($self, $loop, $peer, $tx, $handle, $cb) = @_;
110
111 my $t = $self->transactor;
112 my ($proto, $host, $port) = $peer ? $t->peer($tx) : $t->endpoint($tx);
113
114 my %options = (
115 timeout => $self->connect_timeout,
116 stream_class => 'Mojo::IOLoop::Stream::HTTPClient'
117 );
118 if ($proto eq 'http+unix') { $options{path} = $host }
119 else { @options{qw(address port)} = ($host, $port) }
120 if (my $local = $self->local_address) { $options{local_address} = $local }
121 $options{handle} = $handle if $handle;
122
123 # SOCKS
124 if ($proto eq 'socks') {
125 @options{qw(socks_address socks_port)} = @options{qw(address port)};
126 ($proto, @options{qw(address port)}) = $t->endpoint($tx);
127 my $userinfo = $tx->req->via_proxy(0)->proxy->userinfo;
128 @options{qw(socks_user socks_pass)} = split ':', $userinfo if $userinfo;
129 }
130
131 # TLS
132 if ($options{tls} = $proto eq 'https') {
133 map { $options{"tls_$_"} = $self->$_ } qw(ca cert key);
134 $options{tls_verify} = 0x00 if $self->insecure;
135 }
136
137 weaken $self;
138 my $id;
139 return $id = $loop->client(
140 %options => sub {
141 my ($loop, $err, $stream) = @_;
142
143 # Connection error
144 return unless $self;
145 return $self->_error($id, $err) if $err;
146
147 # Connection established
148 $stream->on(timeout => sub { $self->_error($id, 'Inactivity timeout') });
149 $stream->on(close => sub { $self && $self->_finish($id, 1) });
150 $stream->on(error => sub { $self && $self->_error($id, pop) });
151 $stream->on(upgrade => sub { $self->_upgrade($id, pop) });
152 $self->$cb($id);
153 }
154 );
155}
156
157sub _connect_proxy {
158 my ($self, $loop, $old, $cb) = @_;
159
160 # Start CONNECT request
161 return undef unless my $new = $self->transactor->proxy_connect($old);
162 return $self->_start(
163 ($loop, $new) => sub {
164 my ($self, $tx) = @_;
165
166 # CONNECT failed
167 $old->previous($tx)->req->via_proxy(0);
168 my $id = $tx->connection;
169 if ($tx->error || !$tx->res->is_success || !$tx->keep_alive) {
170 $old->res->error({message => 'Proxy connection failed'});
171 $self->_remove($id) if $id;
172 return $self->$cb($old);
173 }
174
175 # Start real transaction without TLS upgrade
176 return $self->_start($loop, $old->connection($id), $cb)
177 unless $tx->req->url->protocol eq 'https';
178
179 # TLS upgrade before starting the real transaction
180 my $handle = $loop->stream($id)->steal_handle;
181 $self->_remove($id);
182 $id = $self->_connect($loop, 0, $old, $handle,
183 sub { shift->_start($loop, $old->connection($id), $cb) });
184 $self->{connections}{$id} = {cb => $cb, ioloop => $loop, tx => $old};
185 }
186 );
187}
188
189sub _connected {
190 my ($self, $id) = @_;
191
192 my $c = $self->{connections}{$id};
193 my $stream = $c->{ioloop}->stream($id)->timeout($self->inactivity_timeout)
194 ->request_timeout($self->request_timeout);
195 my $tx = $c->{tx}->connection($id);
196
197 weaken $self;
198 $tx->on(finish => sub { $self->_finish($id) });
199 $stream->process($tx);
200}
201
202sub _connection {
203 my ($self, $loop, $tx, $cb) = @_;
204
205 # Reuse connection
206 my ($proto, $host, $port) = $self->transactor->endpoint($tx);
207 my $id = $tx->connection || $self->_dequeue($loop, "$proto:$host:$port", 1);
208 if ($id) {
209 warn "-- Reusing connection $id ($proto://$host:$port)\n" if DEBUG;
210 @{$self->{connections}{$id}}{qw(cb tx)} = ($cb, $tx);
211 $tx->kept_alive(1) unless $tx->connection;
212 $self->_connected($id);
213 return $id;
214 }
215
216 # CONNECT request to proxy required
217 if (my $id = $self->_connect_proxy($loop, $tx, $cb)) { return $id }
218
219 # New connection
220 $tx->res->error({message => "Unsupported protocol: $proto"})
221 and return $loop->next_tick(sub { $self->$cb($tx) })
222 unless $proto eq 'http' || $proto eq 'https' || $proto eq 'http+unix';
223 $id = $self->_connect($loop, 1, $tx, undef, \&_connected);
224 warn "-- Connect $id ($proto://$host:$port)\n" if DEBUG;
225 $self->{connections}{$id} = {cb => $cb, ioloop => $loop, tx => $tx};
226
227 return $id;
228}
229
230sub _dequeue {
231 my ($self, $loop, $name, $test) = @_;
232
233 my $old = $self->{queue}{$loop} ||= [];
234 my ($found, @new);
235 for my $queued (@$old) {
236 push @new, $queued and next if $found || !grep { $_ eq $name } @$queued;
237
238 # Search for id/name and sort out corrupted connections if necessary
239 next unless my $stream = $loop->stream($queued->[1]);
240 $test && $stream->is_readable ? $stream->close : ($found = $queued->[1]);
241 }
242 @$old = @new;
243
244 return $found;
245}
246
247sub _error {
248 my ($self, $id, $err) = @_;
249 my $tx = $self->{connections}{$id}{tx};
250 $tx->closed->res->finish->error({message => $err}) if $tx;
251 $self->_finish($id, 1);
252}
253
254sub _finish {
255 my ($self, $id, $close) = @_;
256
257 return unless my $c = $self->{connections}{$id};
258 return $self->_reuse($id, $close) unless my $tx = $c->{tx};
259
260 $self->cookie_jar->collect($tx);
261
262 $self->_reuse($id, $close) unless uc $tx->req->method eq 'CONNECT';
263 $c->{cb}($self, $tx) unless $self->_redirect($c, $tx);
264}
265
266sub _redirect {
267 my ($self, $c, $old) = @_;
268 return undef unless my $new = $self->transactor->redirect($old);
269 return undef unless @{$old->redirects} < $self->max_redirects;
270 return $self->_start($c->{ioloop}, $new, delete $c->{cb});
271}
272
273sub _remove {
274 my ($self, $id) = @_;
275 my $c = delete $self->{connections}{$id};
276 $self->_dequeue($c->{ioloop}, $id);
277 $c->{ioloop}->remove($id);
278}
279
280sub _reuse {
281 my ($self, $id, $close) = @_;
282
283 # Connection close
284 my $c = $self->{connections}{$id};
285 my $tx = delete $c->{tx};
286 my $max = $self->max_connections;
287 return $self->_remove($id) if $close || !$tx || !$max;
288
289 # Keep connection alive
290 my $queue = $self->{queue}{$c->{ioloop}} ||= [];
291 $self->_remove(shift(@$queue)->[1]) while @$queue && @$queue >= $max;
292 push @$queue, [join(':', $self->transactor->endpoint($tx)), $id];
293}
294
295sub _start {
296 my ($self, $loop, $tx, $cb) = @_;
297
298 # Application serve
299 my $url = $tx->req->url;
300 unless ($url->is_abs) {
301 my $base
302 = $loop == $self->ioloop ? $self->server->url : $self->server->nb_url;
303 $url->scheme($base->scheme)->host($base->host)->port($base->port);
304 }
305
306 $_->prepare($tx) for $self->proxy, $self->cookie_jar;
307 my $max = $self->max_response_size;
308 $tx->res->max_message_size($max) if defined $max;
309
310 $self->emit(start => $tx);
311 return $self->_connection($loop, $tx, $cb);
312}
313
314sub _upgrade {
315 my ($self, $id, $ws) = @_;
316
317 my $c = delete $self->{connections}{$id};
318 my $loop = $c->{ioloop};
319 my $timeout = $loop->stream($id)->timeout;
320 my $stream = $loop->transition($id, 'Mojo::IOLoop::Stream::WebSocketClient');
321 $stream->timeout($timeout);
322
323 weaken $self;
324 $stream->on(timeout => sub { $self->_error($id, 'Inactivity timeout') });
325 $stream->on(close => sub { $self && $self->_remove($id) });
326
327 $self->cookie_jar->collect($ws);
328
329 $c->{cb}($self, $c->{tx} = $ws);
330 $self->{connections}{$id} = $c;
331 $stream->process($ws);
332}
333
334sub _url { shift->req->url->to_abs }
335
3361;
337
338=encoding utf8
339
340=head1 NAME
341
342Mojo::UserAgent - Non-blocking I/O HTTP and WebSocket user agent
343
344=head1 SYNOPSIS
345
346 use Mojo::UserAgent;
347
348 # Fine grained response handling (dies on connection errors)
349 my $ua = Mojo::UserAgent->new;
350 my $res = $ua->get('mojolicious.org/perldoc')->result;
351 if ($res->is_success) { say $res->body }
352 elsif ($res->is_error) { say $res->message }
353 elsif ($res->code == 301) { say $res->headers->location }
354 else { say 'Whatever...' }
355
356 # Say hello to the Unicode snowman and include an Accept header
357 say $ua->get('www.☃.net?hello=there' => {Accept => '*/*'})->result->body;
358
359 # Extract data from HTML and XML resources with CSS selectors
360 say $ua->get('www.perl.org')->result->dom->at('title')->text;
361
362 # Scrape the latest headlines from a news site
363 say $ua->get('blogs.perl.org')
364 ->result->dom->find('h2 > a')->map('text')->join("\n");
365
366 # IPv6 PUT request with Content-Type header and content
367 my $tx = $ua->put('[::1]:3000' => {'Content-Type' => 'text/plain'} => 'Hi!');
368
369 # Quick JSON API request with Basic authentication
370 my $value = $ua->get('https://sri:[email protected]/test.json')->result->json;
371
372 # JSON POST (application/json) with TLS certificate authentication
373 my $tx = $ua->cert('tls.crt')->key('tls.key')
374 ->post('https://example.com' => json => {top => 'secret'});
375
376 # Search DuckDuckGo anonymously through Tor
377 $ua->proxy->http('socks://127.0.0.1:9050');
378 say $ua->get('api.3g2upl4pq6kufc4m.onion/?q=mojolicious&format=json')
379 ->result->json('/Abstract');
380
381 # GET request via UNIX domain socket "/tmp/myapp.sock" (percent encoded slash)
382 say $ua->get('http+unix://%2Ftmp%2Fmyapp.sock/perldoc')->result->body;
383
384 # Follow redirects to download Mojolicious from GitHub
385 $ua->max_redirects(5)
386 ->get('https://www.github.com/kraih/mojo/tarball/master')
387 ->result->content->asset->move_to('/home/sri/mojo.tar.gz');
388
389 # Form POST (application/x-www-form-urlencoded) with manual exception handling
390 my $tx = $ua->post('https://metacpan.org/search' => form => {q => 'mojo'});
391 if (my $res = $tx->success) { say $res->body }
392 else {
393 my $err = $tx->error;
394 die "$err->{code} response: $err->{message}" if $err->{code};
395 die "Connection error: $err->{message}";
396 }
397
398 # Non-blocking request
399 $ua->get('mojolicious.org' => sub {
400 my ($ua, $tx) = @_;
401 say $tx->result->dom->at('title')->text;
402 });
403 Mojo::IOLoop->start unless Mojo::IOLoop->is_running;
404
405 # Concurrent non-blocking requests (synchronized with promises)
406 my $mojo = $ua->get_p('mojolicious.org');
407 my $cpan = $ua->get_p('cpan.org');
408 Mojo::Promise->all($mojo, $cpan)->then(sub {
409 my ($mojo, $cpan) = @_;
410 say $mojo->[0]->result->dom->at('title')->text;
411 say $cpan->[0]->result->dom->at('title')->text;
412 })->wait;
413
414 # WebSocket connection sending and receiving JSON via UNIX domain socket
415 $ua->websocket('ws+unix://%2Ftmp%2Fmyapp.sock/echo.json' => sub {
416 my ($ua, $tx) = @_;
417 say 'WebSocket handshake failed!' and return unless $tx->is_websocket;
418 $tx->on(json => sub {
419 my ($tx, $hash) = @_;
420 say "WebSocket message via JSON: $hash->{msg}";
421 $tx->finish;
422 });
423 $tx->send({json => {msg => 'Hello World!'}});
424 });
425 Mojo::IOLoop->start unless Mojo::IOLoop->is_running;
426
427=head1 DESCRIPTION
428
429L<Mojo::UserAgent> is a full featured non-blocking I/O HTTP and WebSocket user
430agent, with IPv6, TLS, SNI, IDNA, HTTP/SOCKS5 proxy, UNIX domain socket, Comet
431(long polling), Promises/A+, keep-alive, connection pooling, timeout, cookie,
432multipart, gzip compression and multiple event loop support.
433
434All connections will be reset automatically if a new process has been forked,
435this allows multiple processes to share the same L<Mojo::UserAgent> object
436safely.
437
438For better scalability (epoll, kqueue) and to provide non-blocking name
439resolution, SOCKS5 as well as TLS support, the optional modules L<EV> (4.0+),
440L<Net::DNS::Native> (0.15+), L<IO::Socket::Socks> (0.64+) and
441L<IO::Socket::SSL> (2.009+) will be used automatically if possible. Individual
442features can also be disabled with the C<MOJO_NO_NNR>, C<MOJO_NO_SOCKS> and
443C<MOJO_NO_TLS> environment variables.
444
445See L<Mojolicious::Guides::Cookbook/"USER AGENT"> for more.
446
447=head1 EVENTS
448
449L<Mojo::UserAgent> inherits all events from L<Mojo::EventEmitter> and can emit
450the following new ones.
451
452=head2 start
453
454 $ua->on(start => sub {
455 my ($ua, $tx) = @_;
456 ...
457 });
458
459Emitted whenever a new transaction is about to start, this includes
460automatically prepared proxy C<CONNECT> requests and followed redirects.
461
462 $ua->on(start => sub {
463 my ($ua, $tx) = @_;
464 $tx->req->headers->header('X-Bender' => 'Bite my shiny metal ass!');
465 });
466
467=head1 ATTRIBUTES
468
469L<Mojo::UserAgent> implements the following attributes.
470
471=head2 ca
472
473 my $ca = $ua->ca;
474 $ua = $ua->ca('/etc/tls/ca.crt');
475
476Path to TLS certificate authority file used to verify the peer certificate,
477defaults to the value of the C<MOJO_CA_FILE> environment variable.
478
479 # Show certificate authorities for debugging
480 IO::Socket::SSL::set_defaults(
481 SSL_verify_callback => sub { say "Authority: $_[2]" and return $_[0] });
482
483=head2 cert
484
485 my $cert = $ua->cert;
486 $ua = $ua->cert('/etc/tls/client.crt');
487
488Path to TLS certificate file, defaults to the value of the C<MOJO_CERT_FILE>
489environment variable.
490
491=head2 connect_timeout
492
493 my $timeout = $ua->connect_timeout;
494 $ua = $ua->connect_timeout(5);
495
496Maximum amount of time in seconds establishing a connection may take before
497getting canceled, defaults to the value of the C<MOJO_CONNECT_TIMEOUT>
498environment variable or C<10>.
499
500=head2 cookie_jar
501
502 my $cookie_jar = $ua->cookie_jar;
503 $ua = $ua->cookie_jar(Mojo::UserAgent::CookieJar->new);
504
505Cookie jar to use for requests performed by this user agent, defaults to a
506L<Mojo::UserAgent::CookieJar> object.
507
508 # Ignore all cookies
509 $ua->cookie_jar->ignore(sub { 1 });
510
511 # Ignore cookies for public suffixes
512 my $ps = IO::Socket::SSL::PublicSuffix->default;
513 $ua->cookie_jar->ignore(sub {
514 my $cookie = shift;
515 return undef unless my $domain = $cookie->domain;
516 return ($ps->public_suffix($domain))[0] eq '';
517 });
518
519 # Add custom cookie to the jar
520 $ua->cookie_jar->add(
521 Mojo::Cookie::Response->new(
522 name => 'foo',
523 value => 'bar',
524 domain => 'mojolicious.org',
525 path => '/perldoc'
526 )
527 );
528
529=head2 inactivity_timeout
530
531 my $timeout = $ua->inactivity_timeout;
532 $ua = $ua->inactivity_timeout(15);
533
534Maximum amount of time in seconds a connection can be inactive before getting
535closed, defaults to the value of the C<MOJO_INACTIVITY_TIMEOUT> environment
536variable or C<20>. Setting the value to C<0> will allow connections to be
537inactive indefinitely.
538
539=head2 insecure
540
541 my $bool = $ua->insecure;
542 $ua = $ua->insecure($bool);
543
544Do not require a valid TLS certificate to access HTTPS/WSS sites, defaults to
545the value of the C<MOJO_INSECURE> environment variable.
546
547 # Disable TLS certificate verification for testing
548 say $ua->insecure(1)->get('https://127.0.0.1:3000')->result->code;
549
550=head2 ioloop
551
552 my $loop = $ua->ioloop;
553 $ua = $ua->ioloop(Mojo::IOLoop->new);
554
555Event loop object to use for blocking I/O operations, defaults to a
556L<Mojo::IOLoop> object.
557
558=head2 key
559
560 my $key = $ua->key;
561 $ua = $ua->key('/etc/tls/client.crt');
562
563Path to TLS key file, defaults to the value of the C<MOJO_KEY_FILE> environment
564variable.
565
566=head2 local_address
567
568 my $address = $ua->local_address;
569 $ua = $ua->local_address('127.0.0.1');
570
571Local address to bind to.
572
573=head2 max_connections
574
575 my $max = $ua->max_connections;
576 $ua = $ua->max_connections(5);
577
578Maximum number of keep-alive connections that the user agent will retain before
579it starts closing the oldest ones, defaults to C<5>. Setting the value to C<0>
580will prevent any connections from being kept alive.
581
582=head2 max_redirects
583
584 my $max = $ua->max_redirects;
585 $ua = $ua->max_redirects(3);
586
587Maximum number of redirects the user agent will follow before it fails,
588defaults to the value of the C<MOJO_MAX_REDIRECTS> environment variable or
589C<0>.
590
591=head2 max_response_size
592
593 my $max = $ua->max_response_size;
594 $ua = $ua->max_response_size(16777216);
595
596Maximum response size in bytes, defaults to the value of
597L<Mojo::Message::Response/"max_message_size">. Setting the value to C<0> will
598allow responses of indefinite size. Note that increasing this value can also
599drastically increase memory usage, should you for example attempt to parse an
600excessively large response body with the methods L<Mojo::Message/"dom"> or
601L<Mojo::Message/"json">.
602
603=head2 proxy
604
605 my $proxy = $ua->proxy;
606 $ua = $ua->proxy(Mojo::UserAgent::Proxy->new);
607
608Proxy manager, defaults to a L<Mojo::UserAgent::Proxy> object.
609
610 # Detect proxy servers from environment
611 $ua->proxy->detect;
612
613 # Manually configure HTTP proxy (using CONNECT for HTTPS/WebSockets)
614 $ua->proxy->http('http://127.0.0.1:8080')->https('http://127.0.0.1:8080');
615
616 # Manually configure Tor (SOCKS5)
617 $ua->proxy->http('socks://127.0.0.1:9050')->https('socks://127.0.0.1:9050');
618
619 # Manually configure UNIX domain socket (using CONNECT for HTTPS/WebSockets)
620 $ua->proxy->http('http+unix://%2Ftmp%2Fproxy.sock')
621 ->https('http+unix://%2Ftmp%2Fproxy.sock');
622
623=head2 request_timeout
624
625 my $timeout = $ua->request_timeout;
626 $ua = $ua->request_timeout(5);
627
628Maximum amount of time in seconds sending the request and receiving a whole
629response may take before getting canceled, defaults to the value of the
630C<MOJO_REQUEST_TIMEOUT> environment variable or C<0>. This does not include
631L</"connect_timeout">. Setting the value to C<0> will allow the user agent to
632wait indefinitely. The timeout will reset for every followed redirect.
633
634 # Allow 3 seconds to establish connection and 5 seconds to process request
635 $ua->max_redirects(0)->connect_timeout(3)->request_timeout(5);
636
637=head2 server
638
639 my $server = $ua->server;
640 $ua = $ua->server(Mojo::UserAgent::Server->new);
641
642Application server relative URLs will be processed with, defaults to a
643L<Mojo::UserAgent::Server> object.
644
645 # Mock web service
646 $ua->server->app(Mojolicious->new);
647 $ua->server->app->routes->get('/time' => sub {
648 my $c = shift;
649 $c->render(json => {now => time});
650 });
651 my $time = $ua->get('/time')->result->json->{now};
652
653 # Change log level
654 $ua->server->app->log->level('fatal');
655
656 # Port currently used for processing relative URLs blocking
657 say $ua->server->url->port;
658
659 # Port currently used for processing relative URLs non-blocking
660 say $ua->server->nb_url->port;
661
662=head2 transactor
663
664 my $t = $ua->transactor;
665 $ua = $ua->transactor(Mojo::UserAgent::Transactor->new);
666
667Transaction builder, defaults to a L<Mojo::UserAgent::Transactor> object.
668
669 # Change name of user agent
670 $ua->transactor->name('MyUA 1.0');
671
672=head1 METHODS
673
674L<Mojo::UserAgent> inherits all methods from L<Mojo::EventEmitter> and
675implements the following new ones.
676
677=head2 build_tx
678
679 my $tx = $ua->build_tx(GET => 'example.com');
680 my $tx = $ua->build_tx(
681 PUT => 'http://example.com' => {Accept => '*/*'} => 'Content!');
682 my $tx = $ua->build_tx(
683 PUT => 'http://example.com' => {Accept => '*/*'} => form => {a => 'b'});
684 my $tx = $ua->build_tx(
685 PUT => 'http://example.com' => {Accept => '*/*'} => json => {a => 'b'});
686
687Generate L<Mojo::Transaction::HTTP> object with
688L<Mojo::UserAgent::Transactor/"tx">.
689
690 # Request with custom cookie
691 my $tx = $ua->build_tx(GET => 'https://example.com/account');
692 $tx->req->cookies({name => 'user', value => 'sri'});
693 $tx = $ua->start($tx);
694
695 # Deactivate gzip compression
696 my $tx = $ua->build_tx(GET => 'example.com');
697 $tx->req->headers->remove('Accept-Encoding');
698 $tx = $ua->start($tx);
699
700 # Interrupt response by raising an error
701 my $tx = $ua->build_tx(GET => 'http://example.com');
702 $tx->res->on(progress => sub {
703 my $res = shift;
704 return unless my $server = $res->headers->server;
705 $res->error({message => 'Oh noes, it is IIS!'}) if $server =~ /IIS/;
706 });
707 $tx = $ua->start($tx);
708
709=head2 build_websocket_tx
710
711 my $tx = $ua->build_websocket_tx('ws://example.com');
712 my $tx = $ua->build_websocket_tx(
713 'ws://example.com' => {DNT => 1} => ['v1.proto']);
714
715Generate L<Mojo::Transaction::HTTP> object with
716L<Mojo::UserAgent::Transactor/"websocket">.
717
718 # Custom WebSocket handshake with cookie
719 my $tx = $ua->build_websocket_tx('wss://example.com/echo');
720 $tx->req->cookies({name => 'user', value => 'sri'});
721 $ua->start($tx => sub {
722 my ($ua, $tx) = @_;
723 say 'WebSocket handshake failed!' and return unless $tx->is_websocket;
724 $tx->on(message => sub {
725 my ($tx, $msg) = @_;
726 say "WebSocket message: $msg";
727 $tx->finish;
728 });
729 $tx->send('Hi!');
730 });
731 Mojo::IOLoop->start unless Mojo::IOLoop->is_running;
732
733=head2 delete
734
735 my $tx = $ua->delete('example.com');
736 my $tx = $ua->delete('http://example.com' => {Accept => '*/*'} => 'Content!');
737 my $tx = $ua->delete(
738 'http://example.com' => {Accept => '*/*'} => form => {a => 'b'});
739 my $tx = $ua->delete(
740 'http://example.com' => {Accept => '*/*'} => json => {a => 'b'});
741
742Perform blocking C<DELETE> request and return resulting
743L<Mojo::Transaction::HTTP> object, takes the same arguments as
744L<Mojo::UserAgent::Transactor/"tx"> (except for the C<DELETE> method, which is
745implied). You can also append a callback to perform requests non-blocking.
746
747 $ua->delete('http://example.com' => json => {a => 'b'} => sub {
748 my ($ua, $tx) = @_;
749 say $tx->result->body;
750 });
751 Mojo::IOLoop->start unless Mojo::IOLoop->is_running;
752
753=head2 delete_p
754
755 my $promise = $ua->delete_p('http://example.com');
756
757Same as L</"delete">, but performs all requests non-blocking and returns a
758L<Mojo::Promise> object instead of accepting a callback.
759
760 $ua->delete_p('http://example.com' => json => {a => 'b'})->then(sub {
761 my $tx = shift;
762 say $tx->result->body;
763 })->catch(sub {
764 my $err = shift;
765 warn "Connection error: $err";
766 })->wait;
767
768=head2 get
769
770 my $tx = $ua->get('example.com');
771 my $tx = $ua->get('http://example.com' => {Accept => '*/*'} => 'Content!');
772 my $tx = $ua->get(
773 'http://example.com' => {Accept => '*/*'} => form => {a => 'b'});
774 my $tx = $ua->get(
775 'http://example.com' => {Accept => '*/*'} => json => {a => 'b'});
776
777Perform blocking C<GET> request and return resulting L<Mojo::Transaction::HTTP>
778object, takes the same arguments as L<Mojo::UserAgent::Transactor/"tx"> (except
779for the C<GET> method, which is implied). You can also append a callback to
780perform requests non-blocking.
781
782 $ua->get('http://example.com' => json => {a => 'b'} => sub {
783 my ($ua, $tx) = @_;
784 say $tx->result->body;
785 });
786 Mojo::IOLoop->start unless Mojo::IOLoop->is_running;
787
788=head2 get_p
789
790 my $promise = $ua->get_p('http://example.com');
791
792Same as L</"get">, but performs all requests non-blocking and returns a
793L<Mojo::Promise> object instead of accepting a callback.
794
795 $ua->get_p('http://example.com' => json => {a => 'b'})->then(sub {
796 my $tx = shift;
797 say $tx->result->body;
798 })->catch(sub {
799 my $err = shift;
800 warn "Connection error: $err";
801 })->wait;
802
803=head2 head
804
805 my $tx = $ua->head('example.com');
806 my $tx = $ua->head('http://example.com' => {Accept => '*/*'} => 'Content!');
807 my $tx = $ua->head(
808 'http://example.com' => {Accept => '*/*'} => form => {a => 'b'});
809 my $tx = $ua->head(
810 'http://example.com' => {Accept => '*/*'} => json => {a => 'b'});
811
812Perform blocking C<HEAD> request and return resulting
813L<Mojo::Transaction::HTTP> object, takes the same arguments as
814L<Mojo::UserAgent::Transactor/"tx"> (except for the C<HEAD> method, which is
815implied). You can also append a callback to perform requests non-blocking.
816
817 $ua->head('http://example.com' => json => {a => 'b'} => sub {
818 my ($ua, $tx) = @_;
819 say $tx->result->body;
820 });
821 Mojo::IOLoop->start unless Mojo::IOLoop->is_running;
822
823=head2 head_p
824
825 my $promise = $ua->head_p('http://example.com');
826
827Same as L</"head">, but performs all requests non-blocking and returns a
828L<Mojo::Promise> object instead of accepting a callback.
829
830 $ua->head_p('http://example.com' => json => {a => 'b'})->then(sub {
831 my $tx = shift;
832 say $tx->result->body;
833 })->catch(sub {
834 my $err = shift;
835 warn "Connection error: $err";
836 })->wait;
837
838=head2 options
839
840 my $tx = $ua->options('example.com');
841 my $tx = $ua->options('http://example.com' => {Accept => '*/*'} => 'Content!');
842 my $tx = $ua->options(
843 'http://example.com' => {Accept => '*/*'} => form => {a => 'b'});
844 my $tx = $ua->options(
845 'http://example.com' => {Accept => '*/*'} => json => {a => 'b'});
846
847Perform blocking C<OPTIONS> request and return resulting
848L<Mojo::Transaction::HTTP> object, takes the same arguments as
849L<Mojo::UserAgent::Transactor/"tx"> (except for the C<OPTIONS> method, which is
850implied). You can also append a callback to perform requests non-blocking.
851
852 $ua->options('http://example.com' => json => {a => 'b'} => sub {
853 my ($ua, $tx) = @_;
854 say $tx->result->body;
855 });
856 Mojo::IOLoop->start unless Mojo::IOLoop->is_running;
857
858=head2 options_p
859
860 my $promise = $ua->options_p('http://example.com');
861
862Same as L</"options">, but performs all requests non-blocking and returns a
863L<Mojo::Promise> object instead of accepting a callback.
864
865 $ua->options_p('http://example.com' => json => {a => 'b'})->then(sub {
866 my $tx = shift;
867 say $tx->result->body;
868 })->catch(sub {
869 my $err = shift;
870 warn "Connection error: $err";
871 })->wait;
872
873=head2 patch
874
875 my $tx = $ua->patch('example.com');
876 my $tx = $ua->patch('http://example.com' => {Accept => '*/*'} => 'Content!');
877 my $tx = $ua->patch(
878 'http://example.com' => {Accept => '*/*'} => form => {a => 'b'});
879 my $tx = $ua->patch(
880 'http://example.com' => {Accept => '*/*'} => json => {a => 'b'});
881
882Perform blocking C<PATCH> request and return resulting
883L<Mojo::Transaction::HTTP> object, takes the same arguments as
884L<Mojo::UserAgent::Transactor/"tx"> (except for the C<PATCH> method, which is
885implied). You can also append a callback to perform requests non-blocking.
886
887 $ua->patch('http://example.com' => json => {a => 'b'} => sub {
888 my ($ua, $tx) = @_;
889 say $tx->result->body;
890 });
891 Mojo::IOLoop->start unless Mojo::IOLoop->is_running;
892
893=head2 patch_p
894
895 my $promise = $ua->patch_p('http://example.com');
896
897Same as L</"patch">, but performs all requests non-blocking and returns a
898L<Mojo::Promise> object instead of accepting a callback.
899
900 $ua->patch_p('http://example.com' => json => {a => 'b'})->then(sub {
901 my $tx = shift;
902 say $tx->result->body;
903 })->catch(sub {
904 my $err = shift;
905 warn "Connection error: $err";
906 })->wait;
907
908=head2 post
909
910 my $tx = $ua->post('example.com');
911 my $tx = $ua->post('http://example.com' => {Accept => '*/*'} => 'Content!');
912 my $tx = $ua->post(
913 'http://example.com' => {Accept => '*/*'} => form => {a => 'b'});
914 my $tx = $ua->post(
915 'http://example.com' => {Accept => '*/*'} => json => {a => 'b'});
916
917Perform blocking C<POST> request and return resulting
918L<Mojo::Transaction::HTTP> object, takes the same arguments as
919L<Mojo::UserAgent::Transactor/"tx"> (except for the C<POST> method, which is
920implied). You can also append a callback to perform requests non-blocking.
921
922 $ua->post('http://example.com' => json => {a => 'b'} => sub {
923 my ($ua, $tx) = @_;
924 say $tx->result->body;
925 });
926 Mojo::IOLoop->start unless Mojo::IOLoop->is_running;
927
928=head2 post_p
929
930 my $promise = $ua->post_p('http://example.com');
931
932Same as L</"post">, but performs all requests non-blocking and returns a
933L<Mojo::Promise> object instead of accepting a callback.
934
935 $ua->post_p('http://example.com' => json => {a => 'b'})->then(sub {
936 my $tx = shift;
937 say $tx->result->body;
938 })->catch(sub {
939 my $err = shift;
940 warn "Connection error: $err";
941 })->wait;
942
943=head2 put
944
945 my $tx = $ua->put('example.com');
946 my $tx = $ua->put('http://example.com' => {Accept => '*/*'} => 'Content!');
947 my $tx = $ua->put(
948 'http://example.com' => {Accept => '*/*'} => form => {a => 'b'});
949 my $tx = $ua->put(
950 'http://example.com' => {Accept => '*/*'} => json => {a => 'b'});
951
952Perform blocking C<PUT> request and return resulting L<Mojo::Transaction::HTTP>
953object, takes the same arguments as L<Mojo::UserAgent::Transactor/"tx"> (except
954for the C<PUT> method, which is implied). You can also append a callback to
955perform requests non-blocking.
956
957 $ua->put('http://example.com' => json => {a => 'b'} => sub {
958 my ($ua, $tx) = @_;
959 say $tx->result->body;
960 });
961 Mojo::IOLoop->start unless Mojo::IOLoop->is_running;
962
963=head2 put_p
964
965 my $promise = $ua->put_p('http://example.com');
966
967Same as L</"put">, but performs all requests non-blocking and returns a
968L<Mojo::Promise> object instead of accepting a callback.
969
970 $ua->put_p('http://example.com' => json => {a => 'b'})->then(sub {
971 my $tx = shift;
972 say $tx->result->body;
973 })->catch(sub {
974 my $err = shift;
975 warn "Connection error: $err";
976 })->wait;
977
978=head2 start
979
980 my $tx = $ua->start(Mojo::Transaction::HTTP->new);
981
982Perform blocking request for a custom L<Mojo::Transaction::HTTP> object, which
983can be prepared manually or with L</"build_tx">. You can also append a callback
984to perform requests non-blocking.
985
986 my $tx = $ua->build_tx(GET => 'http://example.com');
987 $ua->start($tx => sub {
988 my ($ua, $tx) = @_;
989 say $tx->result->body;
990 });
991 Mojo::IOLoop->start unless Mojo::IOLoop->is_running;
992
993=head2 start_p
994
995 my $promise = $ua->start_p(Mojo::Transaction::HTTP->new);
996
997Same as L</"start">, but performs all requests non-blocking and returns a
998L<Mojo::Promise> object instead of accepting a callback.
999
1000 my $tx = $ua->build_tx(GET => 'http://example.com');
1001 $ua->start_p($tx)->then(sub {
1002 my $tx = shift;
1003 say $tx->result->body;
1004 })->catch(sub {
1005 my $err = shift;
1006 warn "Connection error: $err";
1007 })->wait;
1008
1009=head2 websocket
1010
1011 $ua->websocket('ws://example.com' => sub {...});
1012 $ua->websocket(
1013 'ws://example.com' => {DNT => 1} => ['v1.proto'] => sub {...});
1014
1015Open a non-blocking WebSocket connection with transparent handshake, takes the
1016same arguments as L<Mojo::UserAgent::Transactor/"websocket">. The callback will
1017receive either a L<Mojo::Transaction::WebSocket> or L<Mojo::Transaction::HTTP>
1018object, depending on if the handshake was successful.
1019
1020 $ua->websocket('wss://example.com/echo' => ['v1.proto'] => sub {
1021 my ($ua, $tx) = @_;
1022 say 'WebSocket handshake failed!' and return unless $tx->is_websocket;
1023 say 'Subprotocol negotiation failed!' and return unless $tx->protocol;
1024 $tx->on(finish => sub {
1025 my ($tx, $code, $reason) = @_;
1026 say "WebSocket closed with status $code.";
1027 });
1028 $tx->on(message => sub {
1029 my ($tx, $msg) = @_;
1030 say "WebSocket message: $msg";
1031 $tx->finish;
1032 });
1033 $tx->send('Hi!');
1034 });
1035 Mojo::IOLoop->start unless Mojo::IOLoop->is_running;
1036
1037You can activate C<permessage-deflate> compression by setting the
1038C<Sec-WebSocket-Extensions> header, this can result in much better performance,
1039but also increases memory usage by up to 300KiB per connection.
1040
1041 $ua->websocket('ws://example.com/foo' => {
1042 'Sec-WebSocket-Extensions' => 'permessage-deflate'
1043 } => sub {...});
1044
1045=head2 websocket_p
1046
1047 my $promise = $ua->websocket_p('ws://example.com');
1048
1049Same as L</"websocket">, but returns a L<Mojo::Promise> object instead of
1050accepting a callback.
1051
1052 $ua->websocket_p('wss://example.com/echo')->then(sub {
1053 my $tx = shift;
1054 my $promise = Mojo::Promise->new;
1055 $tx->on(finish => sub { $promise->resolve });
1056 $tx->on(message => sub {
1057 my ($tx, $msg) = @_;
1058 say "WebSocket message: $msg";
1059 $tx->finish;
1060 });
1061 $tx->send('Hi!');
1062 return $promise;
1063 })->catch(sub {
1064 my $err = shift;
1065 warn "WebSocket error: $err";
1066 })->wait;
1067
1068=head1 DEBUGGING
1069
1070You can set the C<MOJO_CLIENT_DEBUG> environment variable to get some advanced
1071diagnostics information printed to C<STDERR>.
1072
1073 MOJO_CLIENT_DEBUG=1
1074
1075=head1 SEE ALSO
1076
1077L<Mojolicious>, L<Mojolicious::Guides>, L<https://mojolicious.org>.
1078
1079=cut
Note: See TracBrowser for help on using the repository browser.