File Coverage

blib/lib/Mojo/UserAgent.pm
Criterion Covered Total %
statement 215 222 96.8
branch 86 102 84.3
condition 52 69 75.3
subroutine 55 56 98.2
pod 6 6 100.0
total 414 455 90.9


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