| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  | #  You may distribute under the terms of either the GNU General Public License | 
| 2 |  |  |  |  |  |  | #  or the Artistic License (the same terms as Perl itself) | 
| 3 |  |  |  |  |  |  | # | 
| 4 |  |  |  |  |  |  | #  (C) Paul Evans, 2008-2023 -- leonerd@leonerd.org.uk | 
| 5 |  |  |  |  |  |  |  | 
| 6 |  |  |  |  |  |  | package Net::Async::HTTP 0.49; | 
| 7 |  |  |  |  |  |  |  | 
| 8 | 40 |  |  | 40 |  | 8419278 | use v5.14; | 
|  | 40 |  |  |  |  | 391 |  | 
| 9 | 40 |  |  | 40 |  | 189 | use warnings; | 
|  | 40 |  |  |  |  | 72 |  | 
|  | 40 |  |  |  |  | 1101 |  | 
| 10 | 40 |  |  | 40 |  | 186 | use base qw( IO::Async::Notifier ); | 
|  | 40 |  |  |  |  | 65 |  | 
|  | 40 |  |  |  |  | 19012 |  | 
| 11 |  |  |  |  |  |  |  | 
| 12 |  |  |  |  |  |  | our $DEFAULT_UA = "Perl + " . __PACKAGE__ . "/$Net::Async::HTTP::VERSION"; | 
| 13 |  |  |  |  |  |  | our $DEFAULT_MAXREDIR = 3; | 
| 14 |  |  |  |  |  |  | our $DEFAULT_MAX_IN_FLIGHT = 4; | 
| 15 |  |  |  |  |  |  | our $DEFAULT_MAX_CONNS_PER_HOST = $ENV{NET_ASYNC_HTTP_MAXCONNS} // 1; | 
| 16 |  |  |  |  |  |  |  | 
| 17 | 40 |  |  | 40 |  | 518432 | use Carp; | 
|  | 40 |  |  |  |  | 92 |  | 
|  | 40 |  |  |  |  | 4173 |  | 
| 18 |  |  |  |  |  |  |  | 
| 19 | 40 |  |  | 40 |  | 17514 | use Net::Async::HTTP::Connection; | 
|  | 40 |  |  |  |  | 277 |  | 
|  | 40 |  |  |  |  | 1330 |  | 
| 20 |  |  |  |  |  |  |  | 
| 21 | 40 |  |  | 40 |  | 16312 | use HTTP::Request; | 
|  | 40 |  |  |  |  | 32913 |  | 
|  | 40 |  |  |  |  | 1119 |  | 
| 22 | 40 |  |  | 40 |  | 16231 | use HTTP::Request::Common qw(); | 
|  | 40 |  |  |  |  | 77223 |  | 
|  | 40 |  |  |  |  | 796 |  | 
| 23 | 40 |  |  | 40 |  | 787 | use URI; | 
|  | 40 |  |  |  |  | 90 |  | 
|  | 40 |  |  |  |  | 1172 |  | 
| 24 |  |  |  |  |  |  |  | 
| 25 | 40 |  |  | 40 |  | 201 | use IO::Async::Stream 0.59; | 
|  | 40 |  |  |  |  | 597 |  | 
|  | 40 |  |  |  |  | 1022 |  | 
| 26 | 40 |  |  | 40 |  | 1008 | use IO::Async::Loop 0.59; # ->connect( handle ) ==> $stream | 
|  | 40 |  |  |  |  | 8553 |  | 
|  | 40 |  |  |  |  | 804 |  | 
| 27 |  |  |  |  |  |  |  | 
| 28 | 40 |  |  | 40 |  | 205 | use Future 0.28; # ->set_label | 
|  | 40 |  |  |  |  | 452 |  | 
|  | 40 |  |  |  |  | 850 |  | 
| 29 | 40 |  |  | 40 |  | 180 | use Future::Utils 0.16 qw( repeat ); | 
|  | 40 |  |  |  |  | 553 |  | 
|  | 40 |  |  |  |  | 2596 |  | 
| 30 |  |  |  |  |  |  |  | 
| 31 | 40 |  |  |  |  | 280 | use Metrics::Any 0.05 '$metrics', | 
| 32 |  |  |  |  |  |  | strict      => 1, | 
| 33 | 40 |  |  | 40 |  | 222 | name_prefix => [qw( http client )]; | 
|  | 40 |  |  |  |  | 529 |  | 
| 34 |  |  |  |  |  |  |  | 
| 35 | 40 |  |  | 40 |  | 3059 | use Scalar::Util qw( blessed reftype ); | 
|  | 40 |  |  |  |  | 73 |  | 
|  | 40 |  |  |  |  | 1902 |  | 
| 36 | 40 |  |  | 40 |  | 225 | use Time::HiRes qw( time ); | 
|  | 40 |  |  |  |  | 79 |  | 
|  | 40 |  |  |  |  | 352 |  | 
| 37 | 40 |  |  | 40 |  | 4719 | use List::Util 1.29 qw( first pairs pairgrep ); | 
|  | 40 |  |  |  |  | 997 |  | 
|  | 40 |  |  |  |  | 3135 |  | 
| 38 | 40 |  |  |  |  | 2839 | use Socket 2.010 qw( | 
| 39 |  |  |  |  |  |  | SOCK_STREAM IPPROTO_IP IP_TOS | 
| 40 |  |  |  |  |  |  | IPTOS_LOWDELAY IPTOS_THROUGHPUT IPTOS_RELIABILITY IPTOS_MINCOST | 
| 41 | 40 |  |  | 40 |  | 244 | ); | 
|  | 40 |  |  |  |  | 638 |  | 
| 42 |  |  |  |  |  |  |  | 
| 43 | 40 |  |  | 40 |  | 243 | use constant HTTP_PORT  => 80; | 
|  | 40 |  |  |  |  | 75 |  | 
|  | 40 |  |  |  |  | 2495 |  | 
| 44 | 40 |  |  | 40 |  | 236 | use constant HTTPS_PORT => 443; | 
|  | 40 |  |  |  |  | 74 |  | 
|  | 40 |  |  |  |  | 2085 |  | 
| 45 |  |  |  |  |  |  |  | 
| 46 | 40 |  |  | 40 |  | 232 | use constant READ_LEN  => 64*1024; # 64 KiB | 
|  | 40 |  |  |  |  | 67 |  | 
|  | 40 |  |  |  |  | 2067 |  | 
| 47 | 40 |  |  | 40 |  | 233 | use constant WRITE_LEN => 64*1024; # 64 KiB | 
|  | 40 |  |  |  |  | 76 |  | 
|  | 40 |  |  |  |  | 1893 |  | 
| 48 |  |  |  |  |  |  |  | 
| 49 | 40 |  |  | 40 |  | 221 | use Struct::Dumb 0.07;  # equallity operator overloading | 
|  | 40 |  |  |  |  | 613 |  | 
|  | 40 |  |  |  |  | 210 |  | 
| 50 |  |  |  |  |  |  | struct Ready => [qw( future connecting )]; | 
| 51 |  |  |  |  |  |  |  | 
| 52 |  |  |  |  |  |  | =head1 NAME | 
| 53 |  |  |  |  |  |  |  | 
| 54 |  |  |  |  |  |  | C<Net::Async::HTTP> - use HTTP with C<IO::Async> | 
| 55 |  |  |  |  |  |  |  | 
| 56 |  |  |  |  |  |  | =head1 SYNOPSIS | 
| 57 |  |  |  |  |  |  |  | 
| 58 |  |  |  |  |  |  | use Future::AsyncAwait; | 
| 59 |  |  |  |  |  |  |  | 
| 60 |  |  |  |  |  |  | use IO::Async::Loop; | 
| 61 |  |  |  |  |  |  | use Net::Async::HTTP; | 
| 62 |  |  |  |  |  |  | use URI; | 
| 63 |  |  |  |  |  |  |  | 
| 64 |  |  |  |  |  |  | my $loop = IO::Async::Loop->new(); | 
| 65 |  |  |  |  |  |  |  | 
| 66 |  |  |  |  |  |  | my $http = Net::Async::HTTP->new(); | 
| 67 |  |  |  |  |  |  |  | 
| 68 |  |  |  |  |  |  | $loop->add( $http ); | 
| 69 |  |  |  |  |  |  |  | 
| 70 |  |  |  |  |  |  | my $response = await $http->do_request( | 
| 71 |  |  |  |  |  |  | uri => URI->new( "http://www.cpan.org/" ), | 
| 72 |  |  |  |  |  |  | ); | 
| 73 |  |  |  |  |  |  |  | 
| 74 |  |  |  |  |  |  | print "Front page of http://www.cpan.org/ is:\n"; | 
| 75 |  |  |  |  |  |  | print $response->as_string; | 
| 76 |  |  |  |  |  |  |  | 
| 77 |  |  |  |  |  |  | =head1 DESCRIPTION | 
| 78 |  |  |  |  |  |  |  | 
| 79 |  |  |  |  |  |  | This object class implements an asynchronous HTTP user agent. It sends | 
| 80 |  |  |  |  |  |  | requests to servers, returning L<Future> instances to yield responses when | 
| 81 |  |  |  |  |  |  | they are received. The object supports multiple concurrent connections to | 
| 82 |  |  |  |  |  |  | servers, and allows multiple requests in the pipeline to any one connection. | 
| 83 |  |  |  |  |  |  | Normally, only one such object will be needed per program to support any | 
| 84 |  |  |  |  |  |  | number of requests. | 
| 85 |  |  |  |  |  |  |  | 
| 86 |  |  |  |  |  |  | As well as using futures the module also supports a callback-based interface. | 
| 87 |  |  |  |  |  |  |  | 
| 88 |  |  |  |  |  |  | This module optionally supports SSL connections, if L<IO::Async::SSL> is | 
| 89 |  |  |  |  |  |  | installed. If so, SSL can be requested either by passing a URI with the | 
| 90 |  |  |  |  |  |  | C<https> scheme, or by passing a true value as the C<SSL> parameter. | 
| 91 |  |  |  |  |  |  |  | 
| 92 |  |  |  |  |  |  | =head2 Connection Pooling | 
| 93 |  |  |  |  |  |  |  | 
| 94 |  |  |  |  |  |  | There are three ways in which connections to HTTP server hosts are managed by | 
| 95 |  |  |  |  |  |  | this object, controlled by the value of C<max_connections_per_host>. This | 
| 96 |  |  |  |  |  |  | controls when new connections are established to servers, as compared to | 
| 97 |  |  |  |  |  |  | waiting for existing connections to be free, as new requests are made to them. | 
| 98 |  |  |  |  |  |  |  | 
| 99 |  |  |  |  |  |  | They are: | 
| 100 |  |  |  |  |  |  |  | 
| 101 |  |  |  |  |  |  | =over 2 | 
| 102 |  |  |  |  |  |  |  | 
| 103 |  |  |  |  |  |  | =item max_connections_per_host = 1 | 
| 104 |  |  |  |  |  |  |  | 
| 105 |  |  |  |  |  |  | This is the default setting. In this mode, there will be one connection per | 
| 106 |  |  |  |  |  |  | host on which there are active or pending requests. If new requests are made | 
| 107 |  |  |  |  |  |  | while an existing one is outstanding, they will be queued to wait for it. | 
| 108 |  |  |  |  |  |  |  | 
| 109 |  |  |  |  |  |  | If pipelining is active on the connection (because both the C<pipeline> option | 
| 110 |  |  |  |  |  |  | is true and the connection is known to be an HTTP/1.1 server), then requests | 
| 111 |  |  |  |  |  |  | will be pipelined into the connection awaiting their response. If not, they | 
| 112 |  |  |  |  |  |  | will be queued awaiting a response to the previous before sending the next. | 
| 113 |  |  |  |  |  |  |  | 
| 114 |  |  |  |  |  |  | =item max_connections_per_host > 1 | 
| 115 |  |  |  |  |  |  |  | 
| 116 |  |  |  |  |  |  | In this mode, there can be more than one connection per host. If a new request | 
| 117 |  |  |  |  |  |  | is made, it will try to re-use idle connections if there are any, or if they | 
| 118 |  |  |  |  |  |  | are all busy it will create a new connection to the host, up to the configured | 
| 119 |  |  |  |  |  |  | limit. | 
| 120 |  |  |  |  |  |  |  | 
| 121 |  |  |  |  |  |  | =item max_connections_per_host = 0 | 
| 122 |  |  |  |  |  |  |  | 
| 123 |  |  |  |  |  |  | In this mode, there is no upper limit to the number of connections per host. | 
| 124 |  |  |  |  |  |  | Every new request will try to reuse an idle connection, or else create a new | 
| 125 |  |  |  |  |  |  | one if all the existing ones are busy. | 
| 126 |  |  |  |  |  |  |  | 
| 127 |  |  |  |  |  |  | =back | 
| 128 |  |  |  |  |  |  |  | 
| 129 |  |  |  |  |  |  | These modes all apply per hostname / server port pair; they do not affect the | 
| 130 |  |  |  |  |  |  | behaviour of connections made to differing hostnames, or differing ports on | 
| 131 |  |  |  |  |  |  | the same hostname. | 
| 132 |  |  |  |  |  |  |  | 
| 133 |  |  |  |  |  |  | =cut | 
| 134 |  |  |  |  |  |  |  | 
| 135 |  |  |  |  |  |  | $metrics->make_gauge( requests_in_flight => | 
| 136 |  |  |  |  |  |  | description => "Count of the number of requests sent that have not yet been completed", | 
| 137 |  |  |  |  |  |  | # no labels | 
| 138 |  |  |  |  |  |  | ); | 
| 139 |  |  |  |  |  |  | $metrics->make_counter( requests  => | 
| 140 |  |  |  |  |  |  | description => "Number of HTTP requests sent", | 
| 141 |  |  |  |  |  |  | labels      => [qw( method )], | 
| 142 |  |  |  |  |  |  | ); | 
| 143 |  |  |  |  |  |  | $metrics->make_counter( responses => | 
| 144 |  |  |  |  |  |  | description => "Number of HTTP responses received", | 
| 145 |  |  |  |  |  |  | labels      => [qw( method code )], | 
| 146 |  |  |  |  |  |  | ); | 
| 147 |  |  |  |  |  |  | $metrics->make_timer( request_duration => | 
| 148 |  |  |  |  |  |  | description => "Duration of time spent waiting for responses", | 
| 149 |  |  |  |  |  |  | # no labels | 
| 150 |  |  |  |  |  |  | ); | 
| 151 |  |  |  |  |  |  | $metrics->make_distribution( response_bytes => | 
| 152 |  |  |  |  |  |  | name        => [qw( response bytes )], | 
| 153 |  |  |  |  |  |  | description => "The size in bytes of responses received", | 
| 154 |  |  |  |  |  |  | units       => "bytes", | 
| 155 |  |  |  |  |  |  | # no labels | 
| 156 |  |  |  |  |  |  | ); | 
| 157 |  |  |  |  |  |  |  | 
| 158 |  |  |  |  |  |  | sub _init | 
| 159 |  |  |  |  |  |  | { | 
| 160 | 40 |  |  | 40 |  | 354021 | my $self = shift; | 
| 161 |  |  |  |  |  |  |  | 
| 162 | 40 |  |  |  |  | 206 | $self->{connections} = {}; # { "$host:$port" } -> [ @connections ] | 
| 163 |  |  |  |  |  |  |  | 
| 164 | 40 |  |  |  |  | 122 | $self->{read_len}  = READ_LEN; | 
| 165 | 40 |  |  |  |  | 99 | $self->{write_len} = WRITE_LEN; | 
| 166 |  |  |  |  |  |  |  | 
| 167 | 40 |  |  |  |  | 94 | $self->{max_connections_per_host} = $DEFAULT_MAX_CONNS_PER_HOST; | 
| 168 |  |  |  |  |  |  |  | 
| 169 | 40 |  |  |  |  | 117 | $self->{ssl_params} = {}; | 
| 170 |  |  |  |  |  |  | } | 
| 171 |  |  |  |  |  |  |  | 
| 172 |  |  |  |  |  |  | sub _remove_from_loop | 
| 173 |  |  |  |  |  |  | { | 
| 174 | 5 |  |  | 5 |  | 7780 | my $self = shift; | 
| 175 |  |  |  |  |  |  |  | 
| 176 | 5 |  |  |  |  | 14 | foreach my $conn ( map { @$_ } values %{ $self->{connections} } ) { | 
|  | 6 |  |  |  |  | 19 |  | 
|  | 5 |  |  |  |  | 19 |  | 
| 177 | 4 |  |  |  |  | 23 | $conn->close; | 
| 178 |  |  |  |  |  |  | } | 
| 179 |  |  |  |  |  |  |  | 
| 180 | 5 |  |  |  |  | 137 | $self->SUPER::_remove_from_loop( @_ ); | 
| 181 |  |  |  |  |  |  | } | 
| 182 |  |  |  |  |  |  |  | 
| 183 |  |  |  |  |  |  | =head1 PARAMETERS | 
| 184 |  |  |  |  |  |  |  | 
| 185 |  |  |  |  |  |  | The following named parameters may be passed to C<new> or C<configure>: | 
| 186 |  |  |  |  |  |  |  | 
| 187 |  |  |  |  |  |  | =head2 user_agent => STRING | 
| 188 |  |  |  |  |  |  |  | 
| 189 |  |  |  |  |  |  | A string to set in the C<User-Agent> HTTP header. If not supplied, one will | 
| 190 |  |  |  |  |  |  | be constructed that declares C<Net::Async::HTTP> and the version number. | 
| 191 |  |  |  |  |  |  |  | 
| 192 |  |  |  |  |  |  | =head2 headers => ARRAY or HASH | 
| 193 |  |  |  |  |  |  |  | 
| 194 |  |  |  |  |  |  | I<Since version 0.45.> | 
| 195 |  |  |  |  |  |  |  | 
| 196 |  |  |  |  |  |  | A set of extra headers to apply to every outgoing request. May be specified | 
| 197 |  |  |  |  |  |  | either as an even-sized array containing key/value pairs, or a hash. | 
| 198 |  |  |  |  |  |  |  | 
| 199 |  |  |  |  |  |  | Individual header values may be added or changed without replacing the entire | 
| 200 |  |  |  |  |  |  | set by using the L<configure> method and passing a key called C<+headers>: | 
| 201 |  |  |  |  |  |  |  | 
| 202 |  |  |  |  |  |  | $http->configure( +headers => { One_More => "Key" } ); | 
| 203 |  |  |  |  |  |  |  | 
| 204 |  |  |  |  |  |  | =head2 max_redirects => INT | 
| 205 |  |  |  |  |  |  |  | 
| 206 |  |  |  |  |  |  | Optional. How many levels of redirection to follow. If not supplied, will | 
| 207 |  |  |  |  |  |  | default to 3. Give 0 to disable redirection entirely. | 
| 208 |  |  |  |  |  |  |  | 
| 209 |  |  |  |  |  |  | =head2 max_in_flight => INT | 
| 210 |  |  |  |  |  |  |  | 
| 211 |  |  |  |  |  |  | Optional. The maximum number of in-flight requests to allow per host when | 
| 212 |  |  |  |  |  |  | pipelining is enabled and supported on that host. If more requests are made | 
| 213 |  |  |  |  |  |  | over this limit they will be queued internally by the object and not sent to | 
| 214 |  |  |  |  |  |  | the server until responses are received. If not supplied, will default to 4. | 
| 215 |  |  |  |  |  |  | Give 0 to disable the limit entirely. | 
| 216 |  |  |  |  |  |  |  | 
| 217 |  |  |  |  |  |  | =head2 max_connections_per_host => INT | 
| 218 |  |  |  |  |  |  |  | 
| 219 |  |  |  |  |  |  | Optional. Controls the maximum number of connections per hostname/server port | 
| 220 |  |  |  |  |  |  | pair, before requests will be queued awaiting one to be free. Give 0 to | 
| 221 |  |  |  |  |  |  | disable the limit entirely. See also the L</Connection Pooling> section | 
| 222 |  |  |  |  |  |  | documented above. | 
| 223 |  |  |  |  |  |  |  | 
| 224 |  |  |  |  |  |  | Currently, if not supplied it will default to 1. However, it has been found in | 
| 225 |  |  |  |  |  |  | practice that most programs will raise this limit to something higher, perhaps | 
| 226 |  |  |  |  |  |  | 3 or 4. Therefore, a future version of this module may set a higher value. | 
| 227 |  |  |  |  |  |  |  | 
| 228 |  |  |  |  |  |  | To test if your application will handle this correctly, you can set a | 
| 229 |  |  |  |  |  |  | different default by setting an environment variable: | 
| 230 |  |  |  |  |  |  |  | 
| 231 |  |  |  |  |  |  | $ NET_ASYNC_HTTP_MAXCONNS=3 perl ... | 
| 232 |  |  |  |  |  |  |  | 
| 233 |  |  |  |  |  |  | =head2 timeout => NUM | 
| 234 |  |  |  |  |  |  |  | 
| 235 |  |  |  |  |  |  | Optional. How long in seconds to wait before giving up on a request. If not | 
| 236 |  |  |  |  |  |  | supplied then no default will be applied, and no timeout will take place. | 
| 237 |  |  |  |  |  |  |  | 
| 238 |  |  |  |  |  |  | =head2 stall_timeout => NUM | 
| 239 |  |  |  |  |  |  |  | 
| 240 |  |  |  |  |  |  | Optional. How long in seconds to wait after each write or read of data on a | 
| 241 |  |  |  |  |  |  | socket, before giving up on a request. This may be more useful than | 
| 242 |  |  |  |  |  |  | C<timeout> on large-file operations, as it will not time out provided that | 
| 243 |  |  |  |  |  |  | regular progress is still being made. | 
| 244 |  |  |  |  |  |  |  | 
| 245 |  |  |  |  |  |  | =head2 proxy_host => STRING | 
| 246 |  |  |  |  |  |  |  | 
| 247 |  |  |  |  |  |  | =head2 proxy_port => INT | 
| 248 |  |  |  |  |  |  |  | 
| 249 |  |  |  |  |  |  | I<Since version 0.10.> | 
| 250 |  |  |  |  |  |  |  | 
| 251 |  |  |  |  |  |  | =head2 proxy_path => PATH | 
| 252 |  |  |  |  |  |  |  | 
| 253 |  |  |  |  |  |  | I<Since version 0.49.> | 
| 254 |  |  |  |  |  |  |  | 
| 255 |  |  |  |  |  |  | Optional. Default values to apply to each C<request> method. | 
| 256 |  |  |  |  |  |  |  | 
| 257 |  |  |  |  |  |  | =head2 cookie_jar => HTTP::Cookies | 
| 258 |  |  |  |  |  |  |  | 
| 259 |  |  |  |  |  |  | Optional. A reference to a L<HTTP::Cookies> object. Will be used to set | 
| 260 |  |  |  |  |  |  | cookies in requests and store them from responses. | 
| 261 |  |  |  |  |  |  |  | 
| 262 |  |  |  |  |  |  | =head2 pipeline => BOOL | 
| 263 |  |  |  |  |  |  |  | 
| 264 |  |  |  |  |  |  | Optional. If false, disables HTTP/1.1-style request pipelining. | 
| 265 |  |  |  |  |  |  |  | 
| 266 |  |  |  |  |  |  | =head2 close_after_request => BOOL | 
| 267 |  |  |  |  |  |  |  | 
| 268 |  |  |  |  |  |  | I<Since version 0.45.> | 
| 269 |  |  |  |  |  |  |  | 
| 270 |  |  |  |  |  |  | Optional. If true, will set the C<Connection: close> header on outgoing | 
| 271 |  |  |  |  |  |  | requests and disable pipelining, thus making every request use a new | 
| 272 |  |  |  |  |  |  | connection. | 
| 273 |  |  |  |  |  |  |  | 
| 274 |  |  |  |  |  |  | =head2 family => INT | 
| 275 |  |  |  |  |  |  |  | 
| 276 |  |  |  |  |  |  | =head2 local_host => STRING | 
| 277 |  |  |  |  |  |  |  | 
| 278 |  |  |  |  |  |  | =head2 local_port => INT | 
| 279 |  |  |  |  |  |  |  | 
| 280 |  |  |  |  |  |  | =head2 local_addrs => ARRAY | 
| 281 |  |  |  |  |  |  |  | 
| 282 |  |  |  |  |  |  | =head2 local_addr => HASH or ARRAY | 
| 283 |  |  |  |  |  |  |  | 
| 284 |  |  |  |  |  |  | Optional. Parameters to pass on to the C<connect> method used to connect | 
| 285 |  |  |  |  |  |  | sockets to HTTP servers. Sets the socket family and local socket address to | 
| 286 |  |  |  |  |  |  | C<bind()> to. For more detail, see the documentation in | 
| 287 |  |  |  |  |  |  | L<IO::Async::Connector>. | 
| 288 |  |  |  |  |  |  |  | 
| 289 |  |  |  |  |  |  | =head2 fail_on_error => BOOL | 
| 290 |  |  |  |  |  |  |  | 
| 291 |  |  |  |  |  |  | Optional. Affects the behaviour of response handling when a C<4xx> or C<5xx> | 
| 292 |  |  |  |  |  |  | response code is received. When false, these responses will be processed as | 
| 293 |  |  |  |  |  |  | other responses and yielded as the result of the future, or passed to the | 
| 294 |  |  |  |  |  |  | C<on_response> callback. When true, such an error response causes the future | 
| 295 |  |  |  |  |  |  | to fail, or the C<on_error> callback to be invoked. | 
| 296 |  |  |  |  |  |  |  | 
| 297 |  |  |  |  |  |  | The HTTP response and request objects will be passed as well as the code and | 
| 298 |  |  |  |  |  |  | message, and the failure name will be C<http>. | 
| 299 |  |  |  |  |  |  |  | 
| 300 |  |  |  |  |  |  | ( $code_message, "http", $response, $request ) = $f->failure | 
| 301 |  |  |  |  |  |  |  | 
| 302 |  |  |  |  |  |  | $on_error->( "$code $message", $response, $request ) | 
| 303 |  |  |  |  |  |  |  | 
| 304 |  |  |  |  |  |  | =head2 read_len => INT | 
| 305 |  |  |  |  |  |  |  | 
| 306 |  |  |  |  |  |  | =head2 write_len => INT | 
| 307 |  |  |  |  |  |  |  | 
| 308 |  |  |  |  |  |  | Optional. Used to set the reading and writing buffer lengths on the underlying | 
| 309 |  |  |  |  |  |  | C<IO::Async::Stream> objects that represent connections to the server. If not | 
| 310 |  |  |  |  |  |  | define, a default of 64 KiB will be used. | 
| 311 |  |  |  |  |  |  |  | 
| 312 |  |  |  |  |  |  | =head2 ip_tos => INT or STRING | 
| 313 |  |  |  |  |  |  |  | 
| 314 |  |  |  |  |  |  | Optional. Used to set the C<IP_TOS> socket option on client sockets. If given, | 
| 315 |  |  |  |  |  |  | should either be a C<IPTOS_*> constant, or one of the string names | 
| 316 |  |  |  |  |  |  | C<lowdelay>, C<throughput>, C<reliability> or C<mincost>. If undefined or left | 
| 317 |  |  |  |  |  |  | absent, no option will be set. | 
| 318 |  |  |  |  |  |  |  | 
| 319 |  |  |  |  |  |  | =head2 decode_content => BOOL | 
| 320 |  |  |  |  |  |  |  | 
| 321 |  |  |  |  |  |  | Optional. If true, incoming responses that have a recognised | 
| 322 |  |  |  |  |  |  | C<Content-Encoding> are handled by the module, and decompressed content is | 
| 323 |  |  |  |  |  |  | passed to the body handling callback or returned in the C<HTTP::Response>. See | 
| 324 |  |  |  |  |  |  | L</CONTENT DECODING> below for details of which encoding types are recognised. | 
| 325 |  |  |  |  |  |  | When this option is enabled, outgoing requests also have the | 
| 326 |  |  |  |  |  |  | C<Accept-Encoding> header added to them if it does not already exist. | 
| 327 |  |  |  |  |  |  |  | 
| 328 |  |  |  |  |  |  | Currently the default is false, because this behaviour is new, but it may | 
| 329 |  |  |  |  |  |  | default to true in a later version. Applications which care which behaviour | 
| 330 |  |  |  |  |  |  | applies should set this to a defined value to ensure it doesn't change. | 
| 331 |  |  |  |  |  |  |  | 
| 332 |  |  |  |  |  |  | =head2 SSL_* | 
| 333 |  |  |  |  |  |  |  | 
| 334 |  |  |  |  |  |  | Additionally, any parameters whose names start with C<SSL_> will be stored and | 
| 335 |  |  |  |  |  |  | passed on requests to perform SSL requests. This simplifies configuration of | 
| 336 |  |  |  |  |  |  | common SSL parameters. | 
| 337 |  |  |  |  |  |  |  | 
| 338 |  |  |  |  |  |  | =head2 require_SSL => BOOL | 
| 339 |  |  |  |  |  |  |  | 
| 340 |  |  |  |  |  |  | Optional. If true, then any attempt to make a request that does not use SSL | 
| 341 |  |  |  |  |  |  | (either by calling C<request>, or as a result of a redirection) will | 
| 342 |  |  |  |  |  |  | immediately fail. | 
| 343 |  |  |  |  |  |  |  | 
| 344 |  |  |  |  |  |  | =head2 SOCKS_* | 
| 345 |  |  |  |  |  |  |  | 
| 346 |  |  |  |  |  |  | I<Since version 0.42.> | 
| 347 |  |  |  |  |  |  |  | 
| 348 |  |  |  |  |  |  | Additionally, any parameters whose names start with C<SOCKS_> will be stored | 
| 349 |  |  |  |  |  |  | and used by L<Net::Async::SOCKS> to establish connections via a configured | 
| 350 |  |  |  |  |  |  | proxy. | 
| 351 |  |  |  |  |  |  |  | 
| 352 |  |  |  |  |  |  | =cut | 
| 353 |  |  |  |  |  |  |  | 
| 354 |  |  |  |  |  |  | sub configure | 
| 355 |  |  |  |  |  |  | { | 
| 356 | 54 |  |  | 54 | 1 | 18913 | my $self = shift; | 
| 357 | 54 |  |  |  |  | 163 | my %params = @_; | 
| 358 |  |  |  |  |  |  |  | 
| 359 | 54 |  |  |  |  | 223 | foreach (qw( user_agent max_redirects max_in_flight max_connections_per_host | 
| 360 |  |  |  |  |  |  | timeout stall_timeout proxy_host proxy_port cookie_jar pipeline | 
| 361 |  |  |  |  |  |  | close_after_request family local_host local_port local_addrs local_addr | 
| 362 |  |  |  |  |  |  | fail_on_error read_len write_len decode_content require_SSL )) | 
| 363 |  |  |  |  |  |  | { | 
| 364 | 1134 | 100 |  |  |  | 1890 | $self->{$_} = delete $params{$_} if exists $params{$_}; | 
| 365 |  |  |  |  |  |  | } | 
| 366 |  |  |  |  |  |  |  | 
| 367 |  |  |  |  |  |  | # Always store internally as ARRAyref | 
| 368 | 54 | 100 |  |  |  | 229 | if( my $headers = delete $params{headers} ) { | 
| 369 | 1 | 50 |  |  |  | 9 | @{ $self->{headers} } = | 
|  | 1 | 50 |  |  |  | 3 |  | 
| 370 |  |  |  |  |  |  | ( ref $headers eq "ARRAY" ) ? @$headers : | 
| 371 |  |  |  |  |  |  | ( ref $headers eq "HASH"  ) ? %$headers : | 
| 372 |  |  |  |  |  |  | croak "Expected 'headers' to be either ARRAY or HASH reference"; | 
| 373 |  |  |  |  |  |  | } | 
| 374 |  |  |  |  |  |  |  | 
| 375 | 54 | 100 |  |  |  | 289 | if( my $more = delete $params{"+headers"} ) { | 
| 376 | 1 | 50 |  |  |  | 9 | my @more = | 
|  |  | 50 |  |  |  |  |  | 
| 377 |  |  |  |  |  |  | ( ref $more eq "ARRAY" ) ? @$more : | 
| 378 |  |  |  |  |  |  | ( ref $more eq "HASH"  ) ? %$more : | 
| 379 |  |  |  |  |  |  | croak "Expected '+headers' to be either ARRAY or HASH reference"; | 
| 380 | 1 |  |  |  |  | 3 | my %to_remove = @more; | 
| 381 |  |  |  |  |  |  |  | 
| 382 | 1 |  |  |  |  | 3 | my $headers = $self->{headers}; | 
| 383 | 1 |  |  | 1 |  | 10 | @$headers = ( ( pairgrep { !exists $to_remove{$a} } @$headers ), @more ); | 
|  | 1 |  |  |  |  | 6 |  | 
| 384 |  |  |  |  |  |  | } | 
| 385 |  |  |  |  |  |  |  | 
| 386 | 54 |  |  |  |  | 203 | foreach ( grep { m/^SSL_/ } keys %params ) { | 
|  | 3 |  |  |  |  | 17 |  | 
| 387 | 1 |  |  |  |  | 4 | $self->{ssl_params}{$_} = delete $params{$_}; | 
| 388 |  |  |  |  |  |  | } | 
| 389 |  |  |  |  |  |  |  | 
| 390 | 54 |  |  |  |  | 155 | foreach ( grep { m/^SOCKS_/ } keys %params ) { | 
|  | 2 |  |  |  |  | 8 |  | 
| 391 | 0 |  |  |  |  | 0 | $self->{socks_params}{$_} = delete $params{$_}; | 
| 392 |  |  |  |  |  |  | } | 
| 393 |  |  |  |  |  |  |  | 
| 394 | 54 | 50 |  |  |  | 177 | if( exists $params{ip_tos} ) { | 
| 395 |  |  |  |  |  |  | # TODO: This conversion should live in IO::Async somewhere | 
| 396 | 0 |  |  |  |  | 0 | my $ip_tos = delete $params{ip_tos}; | 
| 397 | 0 | 0 | 0 |  |  | 0 | $ip_tos = IPTOS_LOWDELAY    if defined $ip_tos and $ip_tos eq "lowdelay"; | 
| 398 | 0 | 0 | 0 |  |  | 0 | $ip_tos = IPTOS_THROUGHPUT  if defined $ip_tos and $ip_tos eq "throughput"; | 
| 399 | 0 | 0 | 0 |  |  | 0 | $ip_tos = IPTOS_RELIABILITY if defined $ip_tos and $ip_tos eq "reliability"; | 
| 400 | 0 | 0 | 0 |  |  | 0 | $ip_tos = IPTOS_MINCOST     if defined $ip_tos and $ip_tos eq "mincost"; | 
| 401 | 0 |  |  |  |  | 0 | $self->{ip_tos} = $ip_tos; | 
| 402 |  |  |  |  |  |  | } | 
| 403 |  |  |  |  |  |  |  | 
| 404 | 54 |  |  |  |  | 348 | $self->SUPER::configure( %params ); | 
| 405 |  |  |  |  |  |  |  | 
| 406 | 54 | 100 |  |  |  | 777 | defined $self->{user_agent}    or $self->{user_agent}    = $DEFAULT_UA; | 
| 407 | 54 | 100 |  |  |  | 289 | defined $self->{max_redirects} or $self->{max_redirects} = $DEFAULT_MAXREDIR; | 
| 408 | 54 | 100 |  |  |  | 223 | defined $self->{max_in_flight} or $self->{max_in_flight} = $DEFAULT_MAX_IN_FLIGHT; | 
| 409 | 54 | 100 |  |  |  | 240 | defined $self->{pipeline}      or $self->{pipeline}      = 1; | 
| 410 |  |  |  |  |  |  | } | 
| 411 |  |  |  |  |  |  |  | 
| 412 |  |  |  |  |  |  | =head1 METHODS | 
| 413 |  |  |  |  |  |  |  | 
| 414 |  |  |  |  |  |  | The following methods documented in an C<await> expression return L<Future> | 
| 415 |  |  |  |  |  |  | instances. | 
| 416 |  |  |  |  |  |  |  | 
| 417 |  |  |  |  |  |  | When returning a Future, the following methods all indicate HTTP-level errors | 
| 418 |  |  |  |  |  |  | using the Future failure name of C<http>. If the error relates to a specific | 
| 419 |  |  |  |  |  |  | response it will be included. The original request is also included. | 
| 420 |  |  |  |  |  |  |  | 
| 421 |  |  |  |  |  |  | $f->fail( $message, "http", $response, $request ) | 
| 422 |  |  |  |  |  |  |  | 
| 423 |  |  |  |  |  |  | =cut | 
| 424 |  |  |  |  |  |  |  | 
| 425 |  |  |  |  |  |  | sub connect_connection | 
| 426 |  |  |  |  |  |  | { | 
| 427 | 105 |  |  | 105 | 0 | 203 | my $self = shift; | 
| 428 | 105 |  |  |  |  | 472 | my %args = @_; | 
| 429 |  |  |  |  |  |  |  | 
| 430 | 105 |  |  |  |  | 236 | my $conn = delete $args{conn}; | 
| 431 | 105 | 100 |  |  |  | 432 | my $key = defined $args{path} ? "unix:$args{path}" : "$args{host}:$args{port}"; | 
| 432 |  |  |  |  |  |  |  | 
| 433 | 105 |  |  |  |  | 213 | my $on_error  = $args{on_error}; | 
| 434 |  |  |  |  |  |  |  | 
| 435 | 105 | 50 |  |  |  | 386 | if( my $socks_params = $self->{socks_params} ) { | 
| 436 | 0 |  |  |  |  | 0 | require Net::Async::SOCKS; | 
| 437 | 0 |  |  |  |  | 0 | Net::Async::SOCKS->VERSION( '0.003' ); | 
| 438 |  |  |  |  |  |  |  | 
| 439 | 0 |  |  |  |  | 0 | unshift @{ $args{extensions} }, "SOCKS"; | 
|  | 0 |  |  |  |  | 0 |  | 
| 440 | 0 |  |  |  |  | 0 | $args{$_} = $socks_params->{$_} for keys %$socks_params; | 
| 441 |  |  |  |  |  |  | } | 
| 442 |  |  |  |  |  |  |  | 
| 443 | 105 | 100 |  |  |  | 318 | if( $args{SSL} ) { | 
| 444 | 3 |  |  |  |  | 30 | require IO::Async::SSL; | 
| 445 | 3 |  |  |  |  | 63 | IO::Async::SSL->VERSION( '0.12' ); # 0.12 has ->connect(handle) bugfix | 
| 446 |  |  |  |  |  |  |  | 
| 447 | 3 |  |  |  |  | 12 | unshift @{ $args{extensions} }, "SSL"; | 
|  | 3 |  |  |  |  | 11 |  | 
| 448 |  |  |  |  |  |  | } | 
| 449 |  |  |  |  |  |  |  | 
| 450 | 105 | 100 |  |  |  | 309 | if( exists $args{port} ) { | 
| 451 | 104 |  |  |  |  | 265 | $args{service} = delete $args{port}; | 
| 452 |  |  |  |  |  |  | } | 
| 453 |  |  |  |  |  |  |  | 
| 454 | 105 | 100 |  |  |  | 333 | unless( exists $args{host} ) { | 
| 455 | 1 |  |  |  |  | 5 | $args{addr} = { family => $args{family}, path => $args{path} }; | 
| 456 |  |  |  |  |  |  | } | 
| 457 |  |  |  |  |  |  |  | 
| 458 |  |  |  |  |  |  | my $f = $conn->connect( | 
| 459 |  |  |  |  |  |  | family   => ( $args{family} || $self->{family} || 0 ), | 
| 460 | 420 | 50 |  |  |  | 1174 | ( map { defined $self->{$_} ? ( $_ => $self->{$_} ) : () } | 
| 461 |  |  |  |  |  |  | qw( local_host local_port local_addrs local_addr ) ), | 
| 462 |  |  |  |  |  |  | %args, | 
| 463 |  |  |  |  |  |  | )->on_done( sub { | 
| 464 | 97 |  |  | 97 |  | 2112 | my ( $stream ) = @_; | 
| 465 | 97 |  |  |  |  | 410 | $stream->configure( | 
| 466 |  |  |  |  |  |  | notifier_name => "$key,fd=" . $stream->read_handle->fileno, | 
| 467 |  |  |  |  |  |  | ); | 
| 468 |  |  |  |  |  |  |  | 
| 469 |  |  |  |  |  |  | # Defend against ->setsockopt doing silly things like detecting SvPOK() | 
| 470 | 97 | 50 |  |  |  | 6986 | $stream->read_handle->setsockopt( IPPROTO_IP, IP_TOS, $self->{ip_tos}+0 ) if defined $self->{ip_tos}; | 
| 471 |  |  |  |  |  |  |  | 
| 472 | 97 |  |  |  |  | 318 | $stream->ready; | 
| 473 |  |  |  |  |  |  | })->on_fail( sub { | 
| 474 | 7 |  |  | 7 |  | 22529 | $on_error->( $conn, "$key - $_[0] failed [$_[-1]]" ); | 
| 475 | 105 |  | 50 |  |  | 885 | }); | 
| 476 |  |  |  |  |  |  |  | 
| 477 | 105 | 100 |  | 22 |  | 80043 | $f->on_ready( sub { undef $f } ) unless $f->is_ready; # intentionally cycle | 
|  | 22 |  |  |  |  | 374 |  | 
| 478 |  |  |  |  |  |  |  | 
| 479 | 105 |  |  |  |  | 1556 | return $f; | 
| 480 |  |  |  |  |  |  | } | 
| 481 |  |  |  |  |  |  |  | 
| 482 |  |  |  |  |  |  | sub get_connection | 
| 483 |  |  |  |  |  |  | { | 
| 484 | 148 |  |  | 148 | 0 | 282 | my $self = shift; | 
| 485 | 148 |  |  |  |  | 454 | my %args = @_; | 
| 486 |  |  |  |  |  |  |  | 
| 487 | 148 | 50 |  |  |  | 576 | my $loop = $self->get_loop or croak "Cannot ->get_connection without a Loop"; | 
| 488 |  |  |  |  |  |  |  | 
| 489 | 148 | 100 |  |  |  | 1308 | my $key = defined $args{path} ? "unix:$args{path}" : "$args{host}:$args{port}"; | 
| 490 | 148 |  | 100 |  |  | 705 | my $conns = $self->{connections}{$key} ||= []; | 
| 491 | 148 |  | 100 |  |  | 595 | my $ready_queue = $self->{ready_queue}{$key} ||= []; | 
| 492 |  |  |  |  |  |  |  | 
| 493 |  |  |  |  |  |  | # Have a look to see if there are any idle connected ones first | 
| 494 | 148 |  |  |  |  | 385 | foreach my $conn ( @$conns ) { | 
| 495 | 53 | 100 | 100 |  |  | 178 | $conn->is_idle and $conn->read_handle and return Future->done( $conn ); | 
| 496 |  |  |  |  |  |  | } | 
| 497 |  |  |  |  |  |  |  | 
| 498 | 134 |  |  |  |  | 312 | my $ready = $args{ready}; | 
| 499 | 134 | 100 |  |  |  | 525 | $ready or push @$ready_queue, $ready = | 
| 500 |  |  |  |  |  |  | Ready( $self->loop->new_future->set_label( "[ready $key]" ), 0 ); | 
| 501 |  |  |  |  |  |  |  | 
| 502 | 134 |  |  |  |  | 34656 | my $f = $ready->future; | 
| 503 |  |  |  |  |  |  |  | 
| 504 | 134 |  |  |  |  | 836 | my $max = $self->{max_connections_per_host}; | 
| 505 | 134 | 100 | 100 |  |  | 637 | if( $max and @$conns >= $max ) { | 
| 506 | 29 |  |  |  |  | 208 | return $f; | 
| 507 |  |  |  |  |  |  | } | 
| 508 |  |  |  |  |  |  |  | 
| 509 |  |  |  |  |  |  | my $conn = Net::Async::HTTP::Connection->new( | 
| 510 |  |  |  |  |  |  | notifier_name => "$key,connecting", | 
| 511 |  |  |  |  |  |  | ready_queue   => $ready_queue, | 
| 512 | 420 |  |  |  |  | 2292 | ( map { $_ => $self->{$_} } | 
| 513 |  |  |  |  |  |  | qw( max_in_flight read_len write_len decode_content ) ), | 
| 514 |  |  |  |  |  |  | pipeline => ( $self->{pipeline} && !$self->{close_after_request} ), | 
| 515 |  |  |  |  |  |  | is_proxy => $args{is_proxy}, | 
| 516 |  |  |  |  |  |  |  | 
| 517 |  |  |  |  |  |  | on_closed => sub { | 
| 518 | 69 |  |  | 69 |  | 195 | my $conn = shift; | 
| 519 | 69 |  |  |  |  | 195 | my $http = $conn->parent; | 
| 520 |  |  |  |  |  |  |  | 
| 521 | 69 |  |  |  |  | 566 | $conn->remove_from_parent; | 
| 522 | 69 |  |  |  |  | 7381 | @$conns = grep { $_ != $conn } @$conns; | 
|  | 69 |  |  |  |  | 293 |  | 
| 523 |  |  |  |  |  |  |  | 
| 524 | 69 | 100 |  |  |  | 779 | if( my $next = first { !$_->connecting } @$ready_queue ) { | 
|  | 2 |  |  |  |  | 9 |  | 
| 525 |  |  |  |  |  |  | # Requeue another connection attempt as there's still more to do | 
| 526 | 2 |  |  |  |  | 91 | $http->get_connection( %args, ready => $next ); | 
| 527 |  |  |  |  |  |  | } | 
| 528 |  |  |  |  |  |  | }, | 
| 529 | 105 |  | 100 |  |  | 363 | ); | 
| 530 |  |  |  |  |  |  |  | 
| 531 | 105 |  |  |  |  | 9775 | $self->add_child( $conn ); | 
| 532 | 105 |  |  |  |  | 12210 | push @$conns, $conn; | 
| 533 |  |  |  |  |  |  |  | 
| 534 |  |  |  |  |  |  | $ready->connecting = $self->connect_connection( %args, | 
| 535 |  |  |  |  |  |  | conn => $conn, | 
| 536 |  |  |  |  |  |  | on_error => sub { | 
| 537 | 7 |  |  | 7 |  | 15 | my $conn = shift; | 
| 538 |  |  |  |  |  |  |  | 
| 539 | 7 | 50 |  |  |  | 26 | $f->fail( @_ ) unless $f->is_cancelled; | 
| 540 |  |  |  |  |  |  |  | 
| 541 | 7 |  |  |  |  | 968 | $conn->remove_from_parent; | 
| 542 | 7 |  |  |  |  | 1134 | @$conns = grep { $_ != $conn } @$conns; | 
|  | 10 |  |  |  |  | 30 |  | 
| 543 | 7 |  |  |  |  | 15 | @$ready_queue = grep { $_ != $ready } @$ready_queue; | 
|  | 12 |  |  |  |  | 125 |  | 
| 544 |  |  |  |  |  |  |  | 
| 545 | 7 | 100 |  |  |  | 76 | if( my $next = first { !$_->connecting } @$ready_queue ) { | 
|  | 5 |  |  |  |  | 19 |  | 
| 546 |  |  |  |  |  |  | # Requeue another connection attempt as there's still more to do | 
| 547 | 2 |  |  |  |  | 32 | $self->get_connection( %args, ready => $next ); | 
| 548 |  |  |  |  |  |  | } | 
| 549 |  |  |  |  |  |  | }, | 
| 550 |  |  |  |  |  |  | )->on_cancel( sub { | 
| 551 | 1 |  |  | 1 |  | 32 | $conn->remove_from_parent; | 
| 552 | 1 |  |  |  |  | 130 | @$conns = grep { $_ != $conn } @$conns; | 
|  | 2 |  |  |  |  | 8 |  | 
| 553 | 105 |  |  |  |  | 876 | }); | 
| 554 |  |  |  |  |  |  |  | 
| 555 | 105 |  |  |  |  | 3197 | return $f; | 
| 556 |  |  |  |  |  |  | } | 
| 557 |  |  |  |  |  |  |  | 
| 558 |  |  |  |  |  |  | =head2 do_request | 
| 559 |  |  |  |  |  |  |  | 
| 560 |  |  |  |  |  |  | $response = await $http->do_request( %args ); | 
| 561 |  |  |  |  |  |  |  | 
| 562 |  |  |  |  |  |  | Send an HTTP request to a server, returning a L<Future> that will yield the | 
| 563 |  |  |  |  |  |  | response. The request may be represented by an L<HTTP::Request> object, or a | 
| 564 |  |  |  |  |  |  | L<URI> object, depending on the arguments passed. | 
| 565 |  |  |  |  |  |  |  | 
| 566 |  |  |  |  |  |  | The following named arguments are used for C<HTTP::Request>s: | 
| 567 |  |  |  |  |  |  |  | 
| 568 |  |  |  |  |  |  | =over 8 | 
| 569 |  |  |  |  |  |  |  | 
| 570 |  |  |  |  |  |  | =item request => HTTP::Request | 
| 571 |  |  |  |  |  |  |  | 
| 572 |  |  |  |  |  |  | A reference to an C<HTTP::Request> object | 
| 573 |  |  |  |  |  |  |  | 
| 574 |  |  |  |  |  |  | =item host => STRING | 
| 575 |  |  |  |  |  |  |  | 
| 576 |  |  |  |  |  |  | Hostname of the server to connect to | 
| 577 |  |  |  |  |  |  |  | 
| 578 |  |  |  |  |  |  | =item port => INT or STRING | 
| 579 |  |  |  |  |  |  |  | 
| 580 |  |  |  |  |  |  | Optional. Port number or service of the server to connect to. If not defined, | 
| 581 |  |  |  |  |  |  | will default to C<http> or C<https> depending on whether SSL is being used. | 
| 582 |  |  |  |  |  |  |  | 
| 583 |  |  |  |  |  |  | =item family => INT or STRING | 
| 584 |  |  |  |  |  |  |  | 
| 585 |  |  |  |  |  |  | Optional. Restricts the socket family for connecting. If not defined, will | 
| 586 |  |  |  |  |  |  | default to the globally-configured value in the object. The value may either | 
| 587 |  |  |  |  |  |  | be a C<PF_*> constant directly, or the lowercase name of one such as C<inet>. | 
| 588 |  |  |  |  |  |  |  | 
| 589 |  |  |  |  |  |  | =item SSL => BOOL | 
| 590 |  |  |  |  |  |  |  | 
| 591 |  |  |  |  |  |  | Optional. If true, an SSL connection will be used. | 
| 592 |  |  |  |  |  |  |  | 
| 593 |  |  |  |  |  |  | =back | 
| 594 |  |  |  |  |  |  |  | 
| 595 |  |  |  |  |  |  | The following named arguments are used for C<URI> requests: | 
| 596 |  |  |  |  |  |  |  | 
| 597 |  |  |  |  |  |  | =over 8 | 
| 598 |  |  |  |  |  |  |  | 
| 599 |  |  |  |  |  |  | =item uri => URI or STRING | 
| 600 |  |  |  |  |  |  |  | 
| 601 |  |  |  |  |  |  | A reference to a C<URI> object, or a plain string giving the request URI. If | 
| 602 |  |  |  |  |  |  | the scheme is C<https> then an SSL connection will be used. | 
| 603 |  |  |  |  |  |  |  | 
| 604 |  |  |  |  |  |  | =item method => STRING | 
| 605 |  |  |  |  |  |  |  | 
| 606 |  |  |  |  |  |  | Optional. The HTTP method name. If missing, C<GET> is used. | 
| 607 |  |  |  |  |  |  |  | 
| 608 |  |  |  |  |  |  | =item content => STRING or ARRAY ref | 
| 609 |  |  |  |  |  |  |  | 
| 610 |  |  |  |  |  |  | Optional. The body content to use for C<PUT> or C<POST> requests. | 
| 611 |  |  |  |  |  |  |  | 
| 612 |  |  |  |  |  |  | If this is a plain scalar it will be used directly, and a C<content_type> | 
| 613 |  |  |  |  |  |  | field must also be supplied to describe it. | 
| 614 |  |  |  |  |  |  |  | 
| 615 |  |  |  |  |  |  | If this is an ARRAY ref and the request method is C<POST>, it will be form | 
| 616 |  |  |  |  |  |  | encoded. It should contain an even-sized list of field names and values. For | 
| 617 |  |  |  |  |  |  | more detail see L<HTTP::Request::Common/POST>. | 
| 618 |  |  |  |  |  |  |  | 
| 619 |  |  |  |  |  |  | =item content_type => STRING | 
| 620 |  |  |  |  |  |  |  | 
| 621 |  |  |  |  |  |  | The type of non-form data C<content>. | 
| 622 |  |  |  |  |  |  |  | 
| 623 |  |  |  |  |  |  | =item user => STRING | 
| 624 |  |  |  |  |  |  |  | 
| 625 |  |  |  |  |  |  | =item pass => STRING | 
| 626 |  |  |  |  |  |  |  | 
| 627 |  |  |  |  |  |  | Optional. If both are given, the HTTP Basic Authorization header will be sent | 
| 628 |  |  |  |  |  |  | with these details. | 
| 629 |  |  |  |  |  |  |  | 
| 630 |  |  |  |  |  |  | =item headers => ARRAY|HASH | 
| 631 |  |  |  |  |  |  |  | 
| 632 |  |  |  |  |  |  | Optional. If provided, contains additional HTTP headers to set on the | 
| 633 |  |  |  |  |  |  | constructed request object. If provided as an ARRAY reference, it should | 
| 634 |  |  |  |  |  |  | contain an even-sized list of name/value pairs. | 
| 635 |  |  |  |  |  |  |  | 
| 636 |  |  |  |  |  |  | =item proxy_host => STRING | 
| 637 |  |  |  |  |  |  |  | 
| 638 |  |  |  |  |  |  | =item proxy_port => INT | 
| 639 |  |  |  |  |  |  |  | 
| 640 |  |  |  |  |  |  | I<Since version 0.10.> | 
| 641 |  |  |  |  |  |  |  | 
| 642 |  |  |  |  |  |  | Optional. Override the hostname or port number implied by the URI. | 
| 643 |  |  |  |  |  |  |  | 
| 644 |  |  |  |  |  |  | =item proxy_path => PATH | 
| 645 |  |  |  |  |  |  |  | 
| 646 |  |  |  |  |  |  | I<Since version 0.49.> | 
| 647 |  |  |  |  |  |  |  | 
| 648 |  |  |  |  |  |  | Optional. Set a UNIX socket path to use as a proxy. To make use of this, also | 
| 649 |  |  |  |  |  |  | set the C<family> argument to C<unix>. | 
| 650 |  |  |  |  |  |  |  | 
| 651 |  |  |  |  |  |  | =back | 
| 652 |  |  |  |  |  |  |  | 
| 653 |  |  |  |  |  |  | For either request type, it takes the following arguments: | 
| 654 |  |  |  |  |  |  |  | 
| 655 |  |  |  |  |  |  | =over 8 | 
| 656 |  |  |  |  |  |  |  | 
| 657 |  |  |  |  |  |  | =item request_body => STRING | CODE | Future | 
| 658 |  |  |  |  |  |  |  | 
| 659 |  |  |  |  |  |  | Optional. Allows request body content to be generated by a future or | 
| 660 |  |  |  |  |  |  | callback, rather than being provided as part of the C<request> object. This | 
| 661 |  |  |  |  |  |  | can either be a plain string, a C<CODE> reference to a generator function, or | 
| 662 |  |  |  |  |  |  | a future. | 
| 663 |  |  |  |  |  |  |  | 
| 664 |  |  |  |  |  |  | As this is passed to the underlying L<IO::Async::Stream> C<write> method, the | 
| 665 |  |  |  |  |  |  | usual semantics apply here. If passed a C<CODE> reference, it will be called | 
| 666 |  |  |  |  |  |  | repeatedly whenever it's safe to write. The code should should return C<undef> | 
| 667 |  |  |  |  |  |  | to indicate completion. If passed a C<Future> it is expected to eventually | 
| 668 |  |  |  |  |  |  | yield the body value. | 
| 669 |  |  |  |  |  |  |  | 
| 670 |  |  |  |  |  |  | As with the C<content> parameter, the C<content_type> field should be | 
| 671 |  |  |  |  |  |  | specified explicitly in the request header, as should the content length | 
| 672 |  |  |  |  |  |  | (typically via the L<HTTP::Request> C<content_length> method). See also | 
| 673 |  |  |  |  |  |  | F<examples/PUT.pl>. | 
| 674 |  |  |  |  |  |  |  | 
| 675 |  |  |  |  |  |  | =item expect_continue => BOOL | 
| 676 |  |  |  |  |  |  |  | 
| 677 |  |  |  |  |  |  | Optional. If true, sets the C<Expect> request header to the value | 
| 678 |  |  |  |  |  |  | C<100-continue> and does not send the C<request_body> parameter until a | 
| 679 |  |  |  |  |  |  | C<100 Continue> response is received from the server. If an error response is | 
| 680 |  |  |  |  |  |  | received then the C<request_body> code, if present, will not be invoked. | 
| 681 |  |  |  |  |  |  |  | 
| 682 |  |  |  |  |  |  | =item on_ready => CODE | 
| 683 |  |  |  |  |  |  |  | 
| 684 |  |  |  |  |  |  | Optional. A callback that is invoked once a socket connection is established | 
| 685 |  |  |  |  |  |  | with the HTTP server, but before the request is actually sent over it. This | 
| 686 |  |  |  |  |  |  | may be used by the client code to inspect the socket, or perform any other | 
| 687 |  |  |  |  |  |  | operations on it. This code is expected to return a C<Future>; only once that | 
| 688 |  |  |  |  |  |  | has completed will the request cycle continue. If it fails, that failure is | 
| 689 |  |  |  |  |  |  | propagated to the caller. | 
| 690 |  |  |  |  |  |  |  | 
| 691 |  |  |  |  |  |  | $f = $on_ready->( $connection ) | 
| 692 |  |  |  |  |  |  |  | 
| 693 |  |  |  |  |  |  | =item on_redirect => CODE | 
| 694 |  |  |  |  |  |  |  | 
| 695 |  |  |  |  |  |  | Optional. A callback that is invoked if a redirect response is received, | 
| 696 |  |  |  |  |  |  | before the new location is fetched. It will be passed the response and the new | 
| 697 |  |  |  |  |  |  | URL. | 
| 698 |  |  |  |  |  |  |  | 
| 699 |  |  |  |  |  |  | $on_redirect->( $response, $location ) | 
| 700 |  |  |  |  |  |  |  | 
| 701 |  |  |  |  |  |  | =item on_body_write => CODE | 
| 702 |  |  |  |  |  |  |  | 
| 703 |  |  |  |  |  |  | Optional. A callback that is invoked after each successful C<syswrite> of the | 
| 704 |  |  |  |  |  |  | body content. This may be used to implement an upload progress indicator or | 
| 705 |  |  |  |  |  |  | similar. It will be passed the total number of bytes of body content written | 
| 706 |  |  |  |  |  |  | so far (i.e. excluding bytes consumed in the header). | 
| 707 |  |  |  |  |  |  |  | 
| 708 |  |  |  |  |  |  | $on_body_write->( $written ) | 
| 709 |  |  |  |  |  |  |  | 
| 710 |  |  |  |  |  |  | =item max_redirects => INT | 
| 711 |  |  |  |  |  |  |  | 
| 712 |  |  |  |  |  |  | Optional. How many levels of redirection to follow. If not supplied, will | 
| 713 |  |  |  |  |  |  | default to the value given in the constructor. | 
| 714 |  |  |  |  |  |  |  | 
| 715 |  |  |  |  |  |  | =item timeout => NUM | 
| 716 |  |  |  |  |  |  |  | 
| 717 |  |  |  |  |  |  | =item stall_timeout => NUM | 
| 718 |  |  |  |  |  |  |  | 
| 719 |  |  |  |  |  |  | Optional. Overrides the object's configured timeout values for this one | 
| 720 |  |  |  |  |  |  | request. If not specified, will use the configured defaults. | 
| 721 |  |  |  |  |  |  |  | 
| 722 |  |  |  |  |  |  | On a timeout, the returned future will fail with either C<timeout> or | 
| 723 |  |  |  |  |  |  | C<stall_timeout> as the operation name. | 
| 724 |  |  |  |  |  |  |  | 
| 725 |  |  |  |  |  |  | ( $message, "timeout" ) = $f->failure | 
| 726 |  |  |  |  |  |  |  | 
| 727 |  |  |  |  |  |  | =back | 
| 728 |  |  |  |  |  |  |  | 
| 729 |  |  |  |  |  |  | =head2 do_request (void) | 
| 730 |  |  |  |  |  |  |  | 
| 731 |  |  |  |  |  |  | $http->do_request( %args ) | 
| 732 |  |  |  |  |  |  |  | 
| 733 |  |  |  |  |  |  | When not returning a future, the following extra arguments are used as | 
| 734 |  |  |  |  |  |  | callbacks instead: | 
| 735 |  |  |  |  |  |  |  | 
| 736 |  |  |  |  |  |  | =over 8 | 
| 737 |  |  |  |  |  |  |  | 
| 738 |  |  |  |  |  |  | =item on_response => CODE | 
| 739 |  |  |  |  |  |  |  | 
| 740 |  |  |  |  |  |  | A callback that is invoked when a response to this request has been received. | 
| 741 |  |  |  |  |  |  | It will be passed an L<HTTP::Response> object containing the response the | 
| 742 |  |  |  |  |  |  | server sent. | 
| 743 |  |  |  |  |  |  |  | 
| 744 |  |  |  |  |  |  | $on_response->( $response ) | 
| 745 |  |  |  |  |  |  |  | 
| 746 |  |  |  |  |  |  | =item on_header => CODE | 
| 747 |  |  |  |  |  |  |  | 
| 748 |  |  |  |  |  |  | Alternative to C<on_response>. A callback that is invoked when the header of a | 
| 749 |  |  |  |  |  |  | response has been received. It is expected to return a C<CODE> reference for | 
| 750 |  |  |  |  |  |  | handling chunks of body content. This C<CODE> reference will be invoked with | 
| 751 |  |  |  |  |  |  | no arguments once the end of the request has been reached, and whatever it | 
| 752 |  |  |  |  |  |  | returns will be used as the result of the returned C<Future>, if there is one. | 
| 753 |  |  |  |  |  |  |  | 
| 754 |  |  |  |  |  |  | $on_body_chunk = $on_header->( $header ) | 
| 755 |  |  |  |  |  |  |  | 
| 756 |  |  |  |  |  |  | $on_body_chunk->( $data ) | 
| 757 |  |  |  |  |  |  | $response = $on_body_chunk->() | 
| 758 |  |  |  |  |  |  |  | 
| 759 |  |  |  |  |  |  | =item on_error => CODE | 
| 760 |  |  |  |  |  |  |  | 
| 761 |  |  |  |  |  |  | A callback that is invoked if an error occurs while trying to send the request | 
| 762 |  |  |  |  |  |  | or obtain the response. It will be passed an error message. | 
| 763 |  |  |  |  |  |  |  | 
| 764 |  |  |  |  |  |  | $on_error->( $message ) | 
| 765 |  |  |  |  |  |  |  | 
| 766 |  |  |  |  |  |  | If this is invoked because of a received C<4xx> or C<5xx> error code in an | 
| 767 |  |  |  |  |  |  | HTTP response, it will be invoked with the response and request objects as | 
| 768 |  |  |  |  |  |  | well. | 
| 769 |  |  |  |  |  |  |  | 
| 770 |  |  |  |  |  |  | $on_error->( $message, $response, $request ) | 
| 771 |  |  |  |  |  |  |  | 
| 772 |  |  |  |  |  |  | =back | 
| 773 |  |  |  |  |  |  |  | 
| 774 |  |  |  |  |  |  | =cut | 
| 775 |  |  |  |  |  |  |  | 
| 776 |  |  |  |  |  |  | sub _do_one_request | 
| 777 |  |  |  |  |  |  | { | 
| 778 | 146 |  |  | 146 |  | 1700 | my $self = shift; | 
| 779 | 146 |  |  |  |  | 726 | my %args = @_; | 
| 780 |  |  |  |  |  |  |  | 
| 781 | 146 |  |  |  |  | 352 | my $host    = delete $args{host}; | 
| 782 | 146 |  |  |  |  | 294 | my $port    = delete $args{port}; | 
| 783 | 146 |  |  |  |  | 246 | my $request = delete $args{request}; | 
| 784 | 146 |  |  |  |  | 258 | my $SSL     = delete $args{SSL}; | 
| 785 |  |  |  |  |  |  |  | 
| 786 | 146 |  |  |  |  | 474 | my $start_time = time; | 
| 787 | 146 |  | 66 |  |  | 685 | my $stall_timeout = $args{stall_timeout} // $self->{stall_timeout}; | 
| 788 |  |  |  |  |  |  |  | 
| 789 | 146 |  |  |  |  | 517 | $self->prepare_request( $request ); | 
| 790 |  |  |  |  |  |  |  | 
| 791 | 146 | 100 | 100 |  |  | 1114 | if( $self->{require_SSL} and not $SSL ) { | 
| 792 | 2 |  |  |  |  | 20 | return Future->fail( "Non-SSL request is not allowed with 'require_SSL' set", | 
| 793 |  |  |  |  |  |  | http => undef, $request ); | 
| 794 |  |  |  |  |  |  | } | 
| 795 |  |  |  |  |  |  |  | 
| 796 | 144 | 100 |  |  |  | 607 | if( $metrics ) { | 
| 797 | 38 |  |  |  |  | 422 | $metrics->inc_gauge( requests_in_flight => ); | 
| 798 | 38 |  |  |  |  | 3785 | $metrics->inc_counter( requests => [ method => $request->method ] ); | 
| 799 |  |  |  |  |  |  | } | 
| 800 |  |  |  |  |  |  |  | 
| 801 | 144 |  |  |  |  | 2926 | my %conn_target; | 
| 802 |  |  |  |  |  |  | my $is_proxy; | 
| 803 |  |  |  |  |  |  |  | 
| 804 | 144 | 100 | 66 |  |  | 1364 | if( defined $args{proxy_host} or ( defined $self->{proxy_host} and not defined $args{proxy_path} ) ) { | 
|  |  | 100 | 66 |  |  |  |  | 
|  |  |  | 66 |  |  |  |  | 
| 805 |  |  |  |  |  |  | %conn_target = ( | 
| 806 |  |  |  |  |  |  | host => $args{proxy_host} || $self->{proxy_host}, | 
| 807 |  |  |  |  |  |  | port => $args{proxy_port} || $self->{proxy_port}, | 
| 808 | 1 |  | 33 |  |  | 11 | ); | 
|  |  |  | 33 |  |  |  |  | 
| 809 | 1 |  |  |  |  | 2 | $is_proxy = 1; | 
| 810 |  |  |  |  |  |  | } | 
| 811 |  |  |  |  |  |  | elsif( defined $args{proxy_path} or defined $self->{proxy_path} ) { | 
| 812 |  |  |  |  |  |  | %conn_target = ( | 
| 813 |  |  |  |  |  |  | path => $args{proxy_path} || $self->{proxy_path}, | 
| 814 | 1 |  | 33 |  |  | 6 | ); | 
| 815 | 1 |  |  |  |  | 2 | $is_proxy = 1; | 
| 816 |  |  |  |  |  |  | } | 
| 817 |  |  |  |  |  |  | else { | 
| 818 | 142 |  |  |  |  | 456 | %conn_target = ( | 
| 819 |  |  |  |  |  |  | host => $host, | 
| 820 |  |  |  |  |  |  | port => $port, | 
| 821 |  |  |  |  |  |  | ); | 
| 822 |  |  |  |  |  |  | } | 
| 823 |  |  |  |  |  |  |  | 
| 824 |  |  |  |  |  |  | return $self->get_connection( | 
| 825 |  |  |  |  |  |  | %conn_target, | 
| 826 |  |  |  |  |  |  | is_proxy => $is_proxy, | 
| 827 |  |  |  |  |  |  | ( defined $args{family} ? ( family => $args{family} ) : () ), | 
| 828 |  |  |  |  |  |  | $SSL ? ( | 
| 829 |  |  |  |  |  |  | SSL  => 1, | 
| 830 |  |  |  |  |  |  | SSL_hostname => $host, | 
| 831 | 5 |  |  |  |  | 27 | %{ $self->{ssl_params} }, | 
| 832 | 10 | 100 |  |  |  | 60 | ( map { m/^SSL_/ ? ( $_ => $args{$_} ) : () } keys %args ), | 
| 833 |  |  |  |  |  |  | ) : (), | 
| 834 |  |  |  |  |  |  | )->then( sub { | 
| 835 | 136 |  |  | 136 |  | 9175 | my ( $conn ) = @_; | 
| 836 | 136 | 100 |  |  |  | 567 | $args{on_ready} ? $args{on_ready}->( $conn )->then_done( $conn ) | 
| 837 |  |  |  |  |  |  | : Future->done( $conn ) | 
| 838 |  |  |  |  |  |  | })->then( sub { | 
| 839 | 136 |  |  | 136 |  | 11343 | my ( $conn ) = @_; | 
| 840 |  |  |  |  |  |  |  | 
| 841 |  |  |  |  |  |  | return $conn->request( | 
| 842 |  |  |  |  |  |  | request => $request, | 
| 843 |  |  |  |  |  |  | stall_timeout => $stall_timeout, | 
| 844 |  |  |  |  |  |  | %args, | 
| 845 |  |  |  |  |  |  | $SSL ? ( SSL => 1 ) : (), | 
| 846 |  |  |  |  |  |  | on_done => sub { | 
| 847 | 122 |  |  |  |  | 1397 | my ( $ctx ) = @_; | 
| 848 |  |  |  |  |  |  |  | 
| 849 | 122 | 100 |  |  |  | 431 | if( $metrics ) { | 
| 850 | 1 |  |  |  |  | 11 | $metrics->dec_gauge( requests_in_flight => ); | 
| 851 |  |  |  |  |  |  | # TODO: Some sort of error counter instead for errors? | 
| 852 | 1 |  |  |  |  | 47 | $metrics->inc_counter( responses => [ method => $request->method, code => $ctx->resp_header->code ] ); | 
| 853 | 1 |  |  |  |  | 93 | $metrics->report_timer( request_duration => time - $start_time ); | 
| 854 | 1 |  |  |  |  | 57 | $metrics->report_distribution( response_bytes => $ctx->resp_bytes ); | 
| 855 |  |  |  |  |  |  | } | 
| 856 |  |  |  |  |  |  | }, | 
| 857 | 136 | 100 |  |  |  | 1204 | ); | 
| 858 | 144 | 100 |  |  |  | 894 | } ); | 
|  |  | 100 |  |  |  |  |  | 
| 859 |  |  |  |  |  |  | } | 
| 860 |  |  |  |  |  |  |  | 
| 861 |  |  |  |  |  |  | sub _should_redirect | 
| 862 |  |  |  |  |  |  | { | 
| 863 | 122 |  |  | 122 |  | 287 | my ( $response ) = @_; | 
| 864 |  |  |  |  |  |  |  | 
| 865 |  |  |  |  |  |  | # Should only redirect if we actually have a Location header | 
| 866 | 122 | 100 | 100 |  |  | 369 | return 0 unless $response->is_redirect and defined $response->header( "Location" ); | 
| 867 |  |  |  |  |  |  |  | 
| 868 | 11 |  |  |  |  | 639 | my $req_method = $response->request->method; | 
| 869 |  |  |  |  |  |  | # Should only redirect GET or HEAD requests | 
| 870 | 11 |  | 66 |  |  | 253 | return $req_method eq "GET" || $req_method eq "HEAD"; | 
| 871 |  |  |  |  |  |  | } | 
| 872 |  |  |  |  |  |  |  | 
| 873 |  |  |  |  |  |  | sub _do_request | 
| 874 |  |  |  |  |  |  | { | 
| 875 | 137 |  |  | 137 |  | 245 | my $self = shift; | 
| 876 | 137 |  |  |  |  | 452 | my %args = @_; | 
| 877 |  |  |  |  |  |  |  | 
| 878 | 137 |  |  |  |  | 288 | my $host = $args{host}; | 
| 879 | 137 |  |  |  |  | 307 | my $port = $args{port}; | 
| 880 | 137 |  |  |  |  | 416 | my $ssl  = $args{SSL}; | 
| 881 |  |  |  |  |  |  |  | 
| 882 | 137 |  |  |  |  | 268 | my $on_header = delete $args{on_header}; | 
| 883 |  |  |  |  |  |  |  | 
| 884 | 137 | 100 |  |  |  | 373 | my $redirects = defined $args{max_redirects} ? $args{max_redirects} : $self->{max_redirects}; | 
| 885 |  |  |  |  |  |  |  | 
| 886 | 137 |  |  |  |  | 237 | my $request = $args{request}; | 
| 887 | 137 |  |  |  |  | 229 | my $response; | 
| 888 |  |  |  |  |  |  | my $reqf; | 
| 889 |  |  |  |  |  |  | # Defeat prototype | 
| 890 |  |  |  |  |  |  | my $future = &repeat( $self->_capture_weakself( sub { | 
| 891 | 146 |  |  | 146 |  | 8397 | my $self = shift; | 
| 892 | 146 |  |  |  |  | 336 | my ( $previous_f ) = @_; | 
| 893 |  |  |  |  |  |  |  | 
| 894 | 146 | 100 |  |  |  | 373 | if( $previous_f ) { | 
| 895 | 9 |  |  |  |  | 61 | my $previous_response = $previous_f->get; | 
| 896 | 9 |  |  |  |  | 139 | $args{previous_response} = $previous_response; | 
| 897 |  |  |  |  |  |  |  | 
| 898 | 9 |  |  |  |  | 28 | my $location = $previous_response->header( "Location" ); | 
| 899 |  |  |  |  |  |  |  | 
| 900 | 9 | 100 |  |  |  | 357 | if( $location =~ m{^http(?:s?)://} ) { | 
|  |  | 50 |  |  |  |  |  | 
| 901 |  |  |  |  |  |  | # skip | 
| 902 |  |  |  |  |  |  | } | 
| 903 |  |  |  |  |  |  | elsif( $location =~ m{^/} ) { | 
| 904 | 3 | 50 |  |  |  | 11 | my $hostport = ( $port != HTTP_PORT ) ? "$host:$port" : $host; | 
| 905 | 3 |  |  |  |  | 71 | $location = "http://$hostport" . $location; | 
| 906 |  |  |  |  |  |  | } | 
| 907 |  |  |  |  |  |  | else { | 
| 908 | 0 |  |  |  |  | 0 | return Future->fail( "Unrecognised Location: $location", http => $previous_response, $request ); | 
| 909 |  |  |  |  |  |  | } | 
| 910 |  |  |  |  |  |  |  | 
| 911 | 9 |  |  |  |  | 69 | my $loc_uri = URI->new( $location ); | 
| 912 | 9 | 50 |  |  |  | 6214 | unless( $loc_uri ) { | 
| 913 | 0 |  |  |  |  | 0 | return Future->fail( "Unable to parse '$location' as a URI", http => $previous_response, $request ); | 
| 914 |  |  |  |  |  |  | } | 
| 915 |  |  |  |  |  |  |  | 
| 916 | 9 |  |  |  |  | 96 | $self->debug_printf( "REDIRECT $loc_uri" ); | 
| 917 |  |  |  |  |  |  |  | 
| 918 | 9 | 100 |  |  |  | 147 | $args{on_redirect}->( $previous_response, $location ) if $args{on_redirect}; | 
| 919 |  |  |  |  |  |  |  | 
| 920 | 9 |  |  |  |  | 68 | %args = $self->_make_request_for_uri( $loc_uri, %args ); | 
| 921 | 9 |  |  |  |  | 25 | $request = $args{request}; | 
| 922 |  |  |  |  |  |  |  | 
| 923 | 9 |  |  |  |  | 26 | undef $host; undef $port; undef $ssl; | 
|  | 9 |  |  |  |  | 13 |  | 
|  | 9 |  |  |  |  | 50 |  | 
| 924 |  |  |  |  |  |  | } | 
| 925 |  |  |  |  |  |  |  | 
| 926 | 146 |  |  |  |  | 425 | my $uri = $request->uri; | 
| 927 | 146 | 100 | 66 |  |  | 1203 | if( defined $uri->scheme and $uri->scheme =~ m/^http(s?)$/ ) { | 
| 928 | 105 | 100 |  |  |  | 4384 | $host = $uri->host if !defined $host; | 
| 929 | 105 | 100 |  |  |  | 558 | $port = $uri->port if !defined $port; | 
| 930 | 105 |  |  |  |  | 650 | $ssl = ( $uri->scheme eq "https" ); | 
| 931 |  |  |  |  |  |  | } | 
| 932 |  |  |  |  |  |  |  | 
| 933 | 146 | 50 |  |  |  | 2546 | defined $host or croak "Expected 'host'"; | 
| 934 | 146 | 50 |  |  |  | 354 | defined $port or $port = ( $ssl ? HTTPS_PORT : HTTP_PORT ); | 
|  |  | 100 |  |  |  |  |  | 
| 935 |  |  |  |  |  |  |  | 
| 936 |  |  |  |  |  |  | return $reqf = $self->_do_one_request( | 
| 937 |  |  |  |  |  |  | host => $host, | 
| 938 |  |  |  |  |  |  | port => $port, | 
| 939 |  |  |  |  |  |  | SSL  => $ssl, | 
| 940 |  |  |  |  |  |  | %args, | 
| 941 |  |  |  |  |  |  | on_header => $self->_capture_weakself( sub { | 
| 942 | 124 |  |  |  |  | 1126 | my $self = shift; | 
| 943 | 124 |  |  |  |  | 273 | ( $response ) = @_; | 
| 944 |  |  |  |  |  |  |  | 
| 945 |  |  |  |  |  |  | # Consume and discard the entire body of a redirect | 
| 946 |  |  |  |  |  |  | return sub { | 
| 947 | 11 | 50 |  |  |  | 37 | return if @_; | 
| 948 | 11 |  |  |  |  | 25 | return $response; | 
| 949 | 124 | 100 | 100 |  |  | 613 | } if $redirects and $response->is_redirect; | 
| 950 |  |  |  |  |  |  |  | 
| 951 | 113 |  |  |  |  | 1254 | return $on_header->( $response ); | 
| 952 | 146 |  |  |  |  | 968 | } ), | 
| 953 |  |  |  |  |  |  | ); | 
| 954 |  |  |  |  |  |  | } ), | 
| 955 |  |  |  |  |  |  | while => sub { | 
| 956 | 139 |  |  | 139 |  | 12438 | my $f = shift; | 
| 957 | 139 | 100 | 66 |  |  | 553 | return 0 if $f->failure or $f->is_cancelled; | 
| 958 | 122 |  | 100 |  |  | 1527 | return _should_redirect( $response ) && $redirects--; | 
| 959 | 137 |  |  |  |  | 1481 | } ); | 
| 960 |  |  |  |  |  |  |  | 
| 961 | 137 | 100 |  |  |  | 21687 | if( $self->{fail_on_error} ) { | 
| 962 |  |  |  |  |  |  | $future = $future->then_with_f( sub { | 
| 963 | 3 |  |  | 3 |  | 239 | my ( $f, $resp ) = @_; | 
| 964 | 3 |  |  |  |  | 7 | my $code = $resp->code; | 
| 965 |  |  |  |  |  |  |  | 
| 966 | 3 | 100 |  |  |  | 36 | if( $code =~ m/^[45]/ ) { | 
| 967 | 2 |  |  |  |  | 5 | my $message = $resp->message; | 
| 968 | 2 |  |  |  |  | 18 | $message =~ s/\r$//; # HTTP::Message bug | 
| 969 |  |  |  |  |  |  |  | 
| 970 | 2 |  |  |  |  | 15 | return Future->fail( "$code $message", http => $resp, $request ); | 
| 971 |  |  |  |  |  |  | } | 
| 972 |  |  |  |  |  |  |  | 
| 973 | 1 |  |  |  |  | 2 | return $f; | 
| 974 | 3 |  |  |  |  | 17 | }); | 
| 975 |  |  |  |  |  |  | } | 
| 976 |  |  |  |  |  |  |  | 
| 977 | 137 |  |  |  |  | 598 | return $future; | 
| 978 |  |  |  |  |  |  | } | 
| 979 |  |  |  |  |  |  |  | 
| 980 |  |  |  |  |  |  | sub do_request | 
| 981 |  |  |  |  |  |  | { | 
| 982 | 137 |  |  | 137 | 1 | 574360 | my $self = shift; | 
| 983 | 137 |  |  |  |  | 622 | my %args = @_; | 
| 984 |  |  |  |  |  |  |  | 
| 985 | 137 | 100 |  |  |  | 1579 | if( my $uri = delete $args{uri} ) { | 
|  |  | 50 |  |  |  |  |  | 
| 986 | 89 |  |  |  |  | 852 | %args = $self->_make_request_for_uri( $uri, %args ); | 
| 987 |  |  |  |  |  |  | } | 
| 988 |  |  |  |  |  |  | elsif( !defined $args{request} ) { | 
| 989 | 0 |  |  |  |  | 0 | croak "Require either 'uri' or 'request' argument"; | 
| 990 |  |  |  |  |  |  | } | 
| 991 |  |  |  |  |  |  |  | 
| 992 | 137 | 100 | 66 |  |  | 742 | if( $args{on_header} ) { | 
|  |  | 50 |  |  |  |  |  | 
| 993 |  |  |  |  |  |  | # ok | 
| 994 |  |  |  |  |  |  | } | 
| 995 |  |  |  |  |  |  | elsif( $args{on_response} or defined wantarray ) { | 
| 996 |  |  |  |  |  |  | $args{on_header} = sub { | 
| 997 | 108 |  |  | 108 |  | 208 | my ( $response ) = @_; | 
| 998 |  |  |  |  |  |  | return sub { | 
| 999 | 186 | 100 |  |  |  | 476 | if( @_ ) { | 
| 1000 | 80 |  |  |  |  | 352 | $response->add_content( @_ ); | 
| 1001 |  |  |  |  |  |  | } | 
| 1002 |  |  |  |  |  |  | else { | 
| 1003 | 106 |  |  |  |  | 239 | return $response; | 
| 1004 |  |  |  |  |  |  | } | 
| 1005 | 108 |  |  |  |  | 637 | }; | 
| 1006 |  |  |  |  |  |  | } | 
| 1007 | 132 |  |  |  |  | 669 | } | 
| 1008 |  |  |  |  |  |  | else { | 
| 1009 | 0 |  |  |  |  | 0 | croak "Expected 'on_response' or 'on_header' as CODE ref or to return a Future"; | 
| 1010 |  |  |  |  |  |  | } | 
| 1011 |  |  |  |  |  |  |  | 
| 1012 | 137 |  |  |  |  | 299 | my $on_error = delete $args{on_error}; | 
| 1013 | 137 | 100 |  |  |  | 392 | my $timeout = defined $args{timeout} ? $args{timeout} : $self->{timeout}; | 
| 1014 |  |  |  |  |  |  |  | 
| 1015 | 137 |  |  |  |  | 562 | my $future = $self->_do_request( %args ); | 
| 1016 |  |  |  |  |  |  |  | 
| 1017 | 137 | 100 |  |  |  | 419 | if( defined $timeout ) { | 
| 1018 |  |  |  |  |  |  | $future = Future->wait_any( | 
| 1019 |  |  |  |  |  |  | $future, | 
| 1020 |  |  |  |  |  |  | $self->loop->timeout_future( after => $timeout ) | 
| 1021 | 34 |  |  | 4 |  | 92 | ->transform( fail => sub { "Timed out", timeout => } ), | 
|  | 4 |  |  |  |  | 494364 |  | 
| 1022 |  |  |  |  |  |  | ); | 
| 1023 |  |  |  |  |  |  | } | 
| 1024 |  |  |  |  |  |  |  | 
| 1025 |  |  |  |  |  |  | $future->on_done( $self->_capture_weakself( sub { | 
| 1026 | 111 |  |  | 111 |  | 14955 | my $self = shift; | 
| 1027 | 111 |  |  |  |  | 189 | my $response = shift; | 
| 1028 | 111 |  |  |  |  | 395 | $self->process_response( $response ); | 
| 1029 | 137 |  |  |  |  | 31291 | } ) ); | 
| 1030 |  |  |  |  |  |  |  | 
| 1031 |  |  |  |  |  |  | $future->on_fail( sub { | 
| 1032 | 8 |  |  | 8 |  | 1661 | my ( $message, $name, @rest ) = @_; | 
| 1033 | 8 |  |  |  |  | 34 | $on_error->( $message, @rest ); | 
| 1034 | 137 | 100 |  |  |  | 4791 | }) if $on_error; | 
| 1035 |  |  |  |  |  |  |  | 
| 1036 | 137 | 100 |  |  |  | 1940 | if( my $on_response = delete $args{on_response} ) { | 
| 1037 |  |  |  |  |  |  | $future->on_done( sub { | 
| 1038 | 74 |  |  | 74 |  | 1643 | my ( $response ) = @_; | 
| 1039 | 74 |  |  |  |  | 210 | $on_response->( $response ); | 
| 1040 | 81 |  |  |  |  | 394 | }); | 
| 1041 |  |  |  |  |  |  | } | 
| 1042 |  |  |  |  |  |  |  | 
| 1043 |  |  |  |  |  |  | # DODGY HACK: | 
| 1044 |  |  |  |  |  |  | # In void context we'll lose reference on the ->wait_any Future, so the | 
| 1045 |  |  |  |  |  |  | # timeout logic will never happen. So lets purposely create a cycle by | 
| 1046 |  |  |  |  |  |  | # capturing the $future in on_done/on_fail closures within itself. This | 
| 1047 |  |  |  |  |  |  | # conveniently clears them out to drop the ref when done. | 
| 1048 | 137 | 100 |  |  |  | 1821 | return $future if defined wantarray; | 
| 1049 |  |  |  |  |  |  |  | 
| 1050 | 54 |  |  | 54 |  | 228 | $future->on_ready( sub { undef $future } ); | 
|  | 54 |  |  |  |  | 9730 |  | 
| 1051 |  |  |  |  |  |  | } | 
| 1052 |  |  |  |  |  |  |  | 
| 1053 |  |  |  |  |  |  | sub _make_request_for_uri | 
| 1054 |  |  |  |  |  |  | { | 
| 1055 | 98 |  |  | 98 |  | 208 | my $self = shift; | 
| 1056 | 98 |  |  |  |  | 311 | my ( $uri, %args ) = @_; | 
| 1057 |  |  |  |  |  |  |  | 
| 1058 | 98 | 100 | 33 |  |  | 974 | if( !ref $uri ) { | 
|  |  | 50 |  |  |  |  |  | 
| 1059 | 17 |  |  |  |  | 150 | $uri = URI->new( $uri ); | 
| 1060 |  |  |  |  |  |  | } | 
| 1061 |  |  |  |  |  |  | elsif( blessed $uri and !$uri->isa( "URI" ) ) { | 
| 1062 | 0 |  |  |  |  | 0 | croak "Expected 'uri' as a URI reference"; | 
| 1063 |  |  |  |  |  |  | } | 
| 1064 |  |  |  |  |  |  |  | 
| 1065 | 98 |  | 100 |  |  | 38476 | my $method = delete $args{method} || "GET"; | 
| 1066 |  |  |  |  |  |  |  | 
| 1067 | 98 |  |  |  |  | 433 | $args{host} = $uri->host; | 
| 1068 | 98 |  |  |  |  | 4288 | $args{port} = $uri->port; | 
| 1069 |  |  |  |  |  |  |  | 
| 1070 | 98 |  |  |  |  | 2351 | my $request; | 
| 1071 |  |  |  |  |  |  |  | 
| 1072 | 98 | 100 |  |  |  | 461 | if( $method eq "POST" ) { | 
| 1073 | 2 | 50 |  |  |  | 6 | defined $args{content} or croak "Expected 'content' with POST method"; | 
| 1074 |  |  |  |  |  |  |  | 
| 1075 |  |  |  |  |  |  | # Lack of content_type didn't used to be a failure condition: | 
| 1076 |  |  |  |  |  |  | ref $args{content} or defined $args{content_type} or | 
| 1077 | 2 | 50 | 66 |  |  | 10 | carp "No 'content_type' was given with 'content'"; | 
| 1078 |  |  |  |  |  |  |  | 
| 1079 |  |  |  |  |  |  | # This will automatically encode a form for us | 
| 1080 | 2 |  |  |  |  | 11 | $request = HTTP::Request::Common::POST( $uri, Content => $args{content}, Content_Type => $args{content_type} ); | 
| 1081 |  |  |  |  |  |  | } | 
| 1082 |  |  |  |  |  |  | else { | 
| 1083 | 96 |  |  |  |  | 780 | $request = HTTP::Request->new( $method, $uri ); | 
| 1084 | 96 | 100 |  |  |  | 6955 | if( defined $args{content} ) { | 
| 1085 | 3 | 50 |  |  |  | 11 | defined $args{content_type} or carp "No 'content_type' was given with 'content'"; | 
| 1086 |  |  |  |  |  |  |  | 
| 1087 | 3 |  |  |  |  | 11 | $request->content( $args{content} ); | 
| 1088 | 3 |  | 50 |  |  | 81 | $request->content_type( $args{content_type} // "" ); | 
| 1089 |  |  |  |  |  |  | } | 
| 1090 |  |  |  |  |  |  | } | 
| 1091 |  |  |  |  |  |  |  | 
| 1092 | 98 |  |  |  |  | 1246 | $request->protocol( "HTTP/1.1" ); | 
| 1093 | 98 | 100 |  |  |  | 950 | if( $args{port} != $uri->default_port ) { | 
| 1094 | 24 |  |  |  |  | 243 | $request->header( Host => "$args{host}:$args{port}" ); | 
| 1095 |  |  |  |  |  |  | } | 
| 1096 |  |  |  |  |  |  | else { | 
| 1097 | 74 |  |  |  |  | 548 | $request->header( Host => "$args{host}" ); | 
| 1098 |  |  |  |  |  |  | } | 
| 1099 |  |  |  |  |  |  |  | 
| 1100 | 98 |  |  |  |  | 5570 | my $headers = $args{headers}; | 
| 1101 | 98 | 100 | 100 |  |  | 795 | if( $headers and reftype $headers eq "ARRAY" ) { | 
|  |  | 100 | 66 |  |  |  |  | 
| 1102 | 1 |  |  |  |  | 13 | $request->header( @$_ ) for pairs @$headers; | 
| 1103 |  |  |  |  |  |  | } | 
| 1104 |  |  |  |  |  |  | elsif( $headers and reftype $headers eq "HASH" ) { | 
| 1105 | 1 |  |  |  |  | 8 | $request->header( $_, $headers->{$_} ) for keys %$headers; | 
| 1106 |  |  |  |  |  |  | } | 
| 1107 |  |  |  |  |  |  |  | 
| 1108 | 98 |  |  |  |  | 313 | my ( $user, $pass ); | 
| 1109 |  |  |  |  |  |  |  | 
| 1110 | 98 | 100 | 66 |  |  | 371 | if( defined $uri->userinfo ) { | 
|  |  | 100 |  |  |  |  |  | 
| 1111 | 1 |  |  |  |  | 22 | ( $user, $pass ) = split( m/:/, $uri->userinfo, 2 ); | 
| 1112 |  |  |  |  |  |  | } | 
| 1113 |  |  |  |  |  |  | elsif( defined $args{user} and defined $args{pass} ) { | 
| 1114 | 1 |  |  |  |  | 21 | $user = $args{user}; | 
| 1115 | 1 |  |  |  |  | 2 | $pass = $args{pass}; | 
| 1116 |  |  |  |  |  |  | } | 
| 1117 |  |  |  |  |  |  |  | 
| 1118 | 98 | 100 | 66 |  |  | 2120 | if( defined $user and defined $pass ) { | 
| 1119 | 2 |  |  |  |  | 12 | $request->authorization_basic( $user, $pass ); | 
| 1120 |  |  |  |  |  |  | } | 
| 1121 |  |  |  |  |  |  |  | 
| 1122 | 98 |  |  |  |  | 1761 | $args{request} = $request; | 
| 1123 |  |  |  |  |  |  |  | 
| 1124 | 98 |  |  |  |  | 615 | return %args; | 
| 1125 |  |  |  |  |  |  | } | 
| 1126 |  |  |  |  |  |  |  | 
| 1127 |  |  |  |  |  |  | =head2 GET, HEAD, PUT, ... | 
| 1128 |  |  |  |  |  |  |  | 
| 1129 |  |  |  |  |  |  | $response = await $http->GET( $uri, %args ); | 
| 1130 |  |  |  |  |  |  |  | 
| 1131 |  |  |  |  |  |  | $response = await $http->HEAD( $uri, %args ); | 
| 1132 |  |  |  |  |  |  |  | 
| 1133 |  |  |  |  |  |  | $response = await $http->PUT( $uri, $content, %args ); | 
| 1134 |  |  |  |  |  |  |  | 
| 1135 |  |  |  |  |  |  | $response = await $http->POST( $uri, $content, %args ); | 
| 1136 |  |  |  |  |  |  |  | 
| 1137 |  |  |  |  |  |  | I<Since version 0.36.> | 
| 1138 |  |  |  |  |  |  |  | 
| 1139 |  |  |  |  |  |  | $response = await $http->PATCH( $uri, $content, %args ); | 
| 1140 |  |  |  |  |  |  |  | 
| 1141 |  |  |  |  |  |  | I<Since version 0.48.> | 
| 1142 |  |  |  |  |  |  |  | 
| 1143 |  |  |  |  |  |  | $response = await $http->DELETE( $uri, %args ); | 
| 1144 |  |  |  |  |  |  |  | 
| 1145 |  |  |  |  |  |  | I<Since version 0.49.> | 
| 1146 |  |  |  |  |  |  |  | 
| 1147 |  |  |  |  |  |  | Convenient wrappers for performing C<GET>, C<HEAD>, C<PUT>, C<POST>, C<PATCH> | 
| 1148 |  |  |  |  |  |  | or C<DELETE> requests with a C<URI> object and few if any other arguments, | 
| 1149 |  |  |  |  |  |  | returning a C<Future>. | 
| 1150 |  |  |  |  |  |  |  | 
| 1151 |  |  |  |  |  |  | Remember that C<POST> with non-form data (as indicated by a plain scalar | 
| 1152 |  |  |  |  |  |  | instead of an C<ARRAY> reference of form data name/value pairs) needs a | 
| 1153 |  |  |  |  |  |  | C<content_type> key in C<%args>. | 
| 1154 |  |  |  |  |  |  |  | 
| 1155 |  |  |  |  |  |  | =cut | 
| 1156 |  |  |  |  |  |  |  | 
| 1157 |  |  |  |  |  |  | sub GET | 
| 1158 |  |  |  |  |  |  | { | 
| 1159 | 10 |  |  | 10 | 1 | 6901 | my $self = shift; | 
| 1160 | 10 |  |  |  |  | 28 | my ( $uri, @args ) = @_; | 
| 1161 | 10 |  |  |  |  | 43 | return $self->do_request( method => "GET", uri => $uri, @args ); | 
| 1162 |  |  |  |  |  |  | } | 
| 1163 |  |  |  |  |  |  |  | 
| 1164 |  |  |  |  |  |  | sub HEAD | 
| 1165 |  |  |  |  |  |  | { | 
| 1166 | 0 |  |  | 0 | 1 | 0 | my $self = shift; | 
| 1167 | 0 |  |  |  |  | 0 | my ( $uri, @args ) = @_; | 
| 1168 | 0 |  |  |  |  | 0 | return $self->do_request( method => "HEAD", uri => $uri, @args ); | 
| 1169 |  |  |  |  |  |  | } | 
| 1170 |  |  |  |  |  |  |  | 
| 1171 |  |  |  |  |  |  | sub PUT | 
| 1172 |  |  |  |  |  |  | { | 
| 1173 | 0 |  |  | 0 | 1 | 0 | my $self = shift; | 
| 1174 | 0 |  |  |  |  | 0 | my ( $uri, $content, @args ) = @_; | 
| 1175 | 0 |  |  |  |  | 0 | return $self->do_request( method => "PUT", uri => $uri, content => $content, @args ); | 
| 1176 |  |  |  |  |  |  | } | 
| 1177 |  |  |  |  |  |  |  | 
| 1178 |  |  |  |  |  |  | sub POST | 
| 1179 |  |  |  |  |  |  | { | 
| 1180 | 0 |  |  | 0 | 0 | 0 | my $self = shift; | 
| 1181 | 0 |  |  |  |  | 0 | my ( $uri, $content, @args ) = @_; | 
| 1182 | 0 |  |  |  |  | 0 | return $self->do_request( method => "POST", uri => $uri, content => $content, @args ); | 
| 1183 |  |  |  |  |  |  | } | 
| 1184 |  |  |  |  |  |  |  | 
| 1185 |  |  |  |  |  |  | sub PATCH | 
| 1186 |  |  |  |  |  |  | { | 
| 1187 | 0 |  |  | 0 | 0 | 0 | my $self = shift; | 
| 1188 | 0 |  |  |  |  | 0 | my ( $uri, $content, @args ) = @_; | 
| 1189 | 0 |  |  |  |  | 0 | return $self->do_request( method => "PATCH", uri => $uri, content => $content, @args ); | 
| 1190 |  |  |  |  |  |  | } | 
| 1191 |  |  |  |  |  |  |  | 
| 1192 |  |  |  |  |  |  | sub DELETE | 
| 1193 |  |  |  |  |  |  | { | 
| 1194 | 0 |  |  | 0 |  | 0 | my $self = shift; | 
| 1195 | 0 |  |  |  |  | 0 | my ( $uri, @args ) = @_; | 
| 1196 | 0 |  |  |  |  | 0 | return $self->do_request( method => "DELETE", uri => $uri, @args ); | 
| 1197 |  |  |  |  |  |  | } | 
| 1198 |  |  |  |  |  |  |  | 
| 1199 |  |  |  |  |  |  | =head1 SUBCLASS METHODS | 
| 1200 |  |  |  |  |  |  |  | 
| 1201 |  |  |  |  |  |  | The following methods are intended as points for subclasses to override, to | 
| 1202 |  |  |  |  |  |  | add extra functionallity. | 
| 1203 |  |  |  |  |  |  |  | 
| 1204 |  |  |  |  |  |  | =cut | 
| 1205 |  |  |  |  |  |  |  | 
| 1206 |  |  |  |  |  |  | =head2 prepare_request | 
| 1207 |  |  |  |  |  |  |  | 
| 1208 |  |  |  |  |  |  | $http->prepare_request( $request ) | 
| 1209 |  |  |  |  |  |  |  | 
| 1210 |  |  |  |  |  |  | Called just before the C<HTTP::Request> object is sent to the server. | 
| 1211 |  |  |  |  |  |  |  | 
| 1212 |  |  |  |  |  |  | =cut | 
| 1213 |  |  |  |  |  |  |  | 
| 1214 |  |  |  |  |  |  | sub prepare_request | 
| 1215 |  |  |  |  |  |  | { | 
| 1216 | 146 |  |  | 146 | 1 | 271 | my $self = shift; | 
| 1217 | 146 |  |  |  |  | 315 | my ( $request ) = @_; | 
| 1218 |  |  |  |  |  |  |  | 
| 1219 | 146 | 100 |  |  |  | 677 | $request->init_header( 'User-Agent' => $self->{user_agent} ) if length $self->{user_agent}; | 
| 1220 | 146 | 100 |  |  |  | 2322 | if( $self->{close_after_request} ) { | 
| 1221 | 1 |  |  |  |  | 4 | $request->header( "Connection" => "close" ); | 
| 1222 |  |  |  |  |  |  | } | 
| 1223 |  |  |  |  |  |  | else { | 
| 1224 | 145 |  |  |  |  | 835 | $request->init_header( "Connection" => "keep-alive" ); | 
| 1225 |  |  |  |  |  |  | } | 
| 1226 |  |  |  |  |  |  |  | 
| 1227 | 146 |  |  |  |  | 6746 | foreach ( pairs @{ $self->{headers} } ) { | 
|  | 146 |  |  |  |  | 1208 |  | 
| 1228 | 3 |  |  |  |  | 61 | $request->init_header( $_->key, $_->value ); | 
| 1229 |  |  |  |  |  |  | } | 
| 1230 |  |  |  |  |  |  |  | 
| 1231 | 146 | 100 |  |  |  | 572 | $self->{cookie_jar}->add_cookie_header( $request ) if $self->{cookie_jar}; | 
| 1232 |  |  |  |  |  |  | } | 
| 1233 |  |  |  |  |  |  |  | 
| 1234 |  |  |  |  |  |  | =head2 process_response | 
| 1235 |  |  |  |  |  |  |  | 
| 1236 |  |  |  |  |  |  | $http->process_response( $response ) | 
| 1237 |  |  |  |  |  |  |  | 
| 1238 |  |  |  |  |  |  | Called after a non-redirect C<HTTP::Response> has been received from a server. | 
| 1239 |  |  |  |  |  |  | The originating request will be set in the object. | 
| 1240 |  |  |  |  |  |  |  | 
| 1241 |  |  |  |  |  |  | =cut | 
| 1242 |  |  |  |  |  |  |  | 
| 1243 |  |  |  |  |  |  | sub process_response | 
| 1244 |  |  |  |  |  |  | { | 
| 1245 | 111 |  |  | 111 | 1 | 219 | my $self = shift; | 
| 1246 | 111 |  |  |  |  | 218 | my ( $response ) = @_; | 
| 1247 |  |  |  |  |  |  |  | 
| 1248 | 111 | 100 |  |  |  | 452 | $self->{cookie_jar}->extract_cookies( $response ) if $self->{cookie_jar}; | 
| 1249 |  |  |  |  |  |  | } | 
| 1250 |  |  |  |  |  |  |  | 
| 1251 |  |  |  |  |  |  | =head1 CONTENT DECODING | 
| 1252 |  |  |  |  |  |  |  | 
| 1253 |  |  |  |  |  |  | If the required decompression modules are installed and available, compressed | 
| 1254 |  |  |  |  |  |  | content can be decoded. If the received C<Content-Encoding> is recognised and | 
| 1255 |  |  |  |  |  |  | the required module is available, the content is transparently decoded and the | 
| 1256 |  |  |  |  |  |  | decoded content is returned in the resulting response object, or passed to the | 
| 1257 |  |  |  |  |  |  | data chunk handler. In this case, the original C<Content-Encoding> header will | 
| 1258 |  |  |  |  |  |  | be deleted from the response, and its value will be available instead as | 
| 1259 |  |  |  |  |  |  | C<X-Original-Content-Encoding>. | 
| 1260 |  |  |  |  |  |  |  | 
| 1261 |  |  |  |  |  |  | The following content encoding types are recognised by these modules: | 
| 1262 |  |  |  |  |  |  |  | 
| 1263 |  |  |  |  |  |  | =over 4 | 
| 1264 |  |  |  |  |  |  |  | 
| 1265 |  |  |  |  |  |  | =cut | 
| 1266 |  |  |  |  |  |  |  | 
| 1267 |  |  |  |  |  |  | =item * gzip (q=0.7) and deflate (q=0.5) | 
| 1268 |  |  |  |  |  |  |  | 
| 1269 |  |  |  |  |  |  | Recognised if L<Compress::Raw::Zlib> version 2.057 or newer is installed. | 
| 1270 |  |  |  |  |  |  |  | 
| 1271 |  |  |  |  |  |  | =cut | 
| 1272 |  |  |  |  |  |  |  | 
| 1273 |  |  |  |  |  |  | if( eval { require Compress::Raw::Zlib and $Compress::Raw::Zlib::VERSION >= 2.057 } ) { | 
| 1274 |  |  |  |  |  |  | my $make_zlib_decoder = sub { | 
| 1275 |  |  |  |  |  |  | my ( $bits ) = @_; | 
| 1276 |  |  |  |  |  |  | my $inflator = Compress::Raw::Zlib::Inflate->new( | 
| 1277 |  |  |  |  |  |  | -ConsumeInput => 0, | 
| 1278 |  |  |  |  |  |  | -WindowBits => $bits, | 
| 1279 |  |  |  |  |  |  | ); | 
| 1280 |  |  |  |  |  |  | sub { | 
| 1281 |  |  |  |  |  |  | my $output; | 
| 1282 |  |  |  |  |  |  | my $status = @_ ? $inflator->inflate( $_[0], $output ) | 
| 1283 |  |  |  |  |  |  | : $inflator->inflate( "", $output, 1 ); | 
| 1284 |  |  |  |  |  |  | die "$status\n" if $status && $status != Compress::Raw::Zlib::Z_STREAM_END(); | 
| 1285 |  |  |  |  |  |  | return $output; | 
| 1286 |  |  |  |  |  |  | }; | 
| 1287 |  |  |  |  |  |  | }; | 
| 1288 |  |  |  |  |  |  |  | 
| 1289 |  |  |  |  |  |  | # RFC1950 | 
| 1290 |  |  |  |  |  |  | __PACKAGE__->register_decoder( | 
| 1291 |  |  |  |  |  |  | deflate => 0.5, sub { $make_zlib_decoder->( 15 ) }, | 
| 1292 |  |  |  |  |  |  | ); | 
| 1293 |  |  |  |  |  |  |  | 
| 1294 |  |  |  |  |  |  | # RFC1952 | 
| 1295 |  |  |  |  |  |  | __PACKAGE__->register_decoder( | 
| 1296 |  |  |  |  |  |  | gzip => 0.7, sub { $make_zlib_decoder->( Compress::Raw::Zlib::WANT_GZIP() ) }, | 
| 1297 |  |  |  |  |  |  | ); | 
| 1298 |  |  |  |  |  |  | } | 
| 1299 |  |  |  |  |  |  |  | 
| 1300 |  |  |  |  |  |  | =item * bzip2 (q=0.8) | 
| 1301 |  |  |  |  |  |  |  | 
| 1302 |  |  |  |  |  |  | Recognised if L<Compress::Bzip2> version 2.10 or newer is installed. | 
| 1303 |  |  |  |  |  |  |  | 
| 1304 |  |  |  |  |  |  | =cut | 
| 1305 |  |  |  |  |  |  |  | 
| 1306 |  |  |  |  |  |  | if( eval { require Compress::Bzip2 and $Compress::Bzip2::VERSION >= 2.10 } ) { | 
| 1307 |  |  |  |  |  |  | __PACKAGE__->register_decoder( | 
| 1308 |  |  |  |  |  |  | bzip2 => 0.8, sub { | 
| 1309 |  |  |  |  |  |  | my $inflator = Compress::Bzip2::inflateInit(); | 
| 1310 |  |  |  |  |  |  | sub { | 
| 1311 |  |  |  |  |  |  | return unless my ( $in ) = @_; | 
| 1312 |  |  |  |  |  |  | my $out = $inflator->bzinflate( \$in ); | 
| 1313 |  |  |  |  |  |  | die $inflator->bzerror."\n" if !defined $out; | 
| 1314 |  |  |  |  |  |  | return $out; | 
| 1315 |  |  |  |  |  |  | }; | 
| 1316 |  |  |  |  |  |  | } | 
| 1317 |  |  |  |  |  |  | ); | 
| 1318 |  |  |  |  |  |  | } | 
| 1319 |  |  |  |  |  |  |  | 
| 1320 |  |  |  |  |  |  | =back | 
| 1321 |  |  |  |  |  |  |  | 
| 1322 |  |  |  |  |  |  | Other content encoding types can be registered by calling the following method | 
| 1323 |  |  |  |  |  |  |  | 
| 1324 |  |  |  |  |  |  | =head2 register_decoder | 
| 1325 |  |  |  |  |  |  |  | 
| 1326 |  |  |  |  |  |  | Net::Async::HTTP->register_decoder( $name, $q, $make_decoder ) | 
| 1327 |  |  |  |  |  |  |  | 
| 1328 |  |  |  |  |  |  | Registers an encoding type called C<$name>, at the quality value C<$q>. In | 
| 1329 |  |  |  |  |  |  | order to decode this encoding type, C<$make_decoder> will be invoked with no | 
| 1330 |  |  |  |  |  |  | paramters, and expected to return a CODE reference to perform one instance of | 
| 1331 |  |  |  |  |  |  | decoding. | 
| 1332 |  |  |  |  |  |  |  | 
| 1333 |  |  |  |  |  |  | $decoder = $make_decoder->() | 
| 1334 |  |  |  |  |  |  |  | 
| 1335 |  |  |  |  |  |  | This decoder will be invoked on string buffers to decode them until | 
| 1336 |  |  |  |  |  |  | the end of stream is reached, when it will be invoked with no arguments. | 
| 1337 |  |  |  |  |  |  |  | 
| 1338 |  |  |  |  |  |  | $content = $decoder->( $encoded_content ) | 
| 1339 |  |  |  |  |  |  | $content = $decoder->() # EOS | 
| 1340 |  |  |  |  |  |  |  | 
| 1341 |  |  |  |  |  |  | =cut | 
| 1342 |  |  |  |  |  |  |  | 
| 1343 |  |  |  |  |  |  | { | 
| 1344 |  |  |  |  |  |  | my %DECODERS; # {$name} = [$q, $make_decoder] | 
| 1345 |  |  |  |  |  |  |  | 
| 1346 |  |  |  |  |  |  | sub register_decoder | 
| 1347 |  |  |  |  |  |  | { | 
| 1348 | 80 |  |  | 80 | 1 | 144 | shift; | 
| 1349 | 80 |  |  |  |  | 171 | my ( $name, $q, $make_decoder ) = @_; | 
| 1350 |  |  |  |  |  |  |  | 
| 1351 | 80 |  |  |  |  | 226 | $DECODERS{$name} = [ $q, $make_decoder ]; | 
| 1352 |  |  |  |  |  |  | } | 
| 1353 |  |  |  |  |  |  |  | 
| 1354 |  |  |  |  |  |  | sub can_decode | 
| 1355 |  |  |  |  |  |  | { | 
| 1356 | 2 |  |  | 2 | 0 | 4 | shift; | 
| 1357 | 2 | 50 |  |  |  | 6 | if( @_ ) { | 
| 1358 | 2 |  |  |  |  | 4 | my ( $name ) = @_; | 
| 1359 |  |  |  |  |  |  |  | 
| 1360 | 2 | 50 |  |  |  | 10 | return unless my $d = $DECODERS{$name}; | 
| 1361 | 2 |  |  |  |  | 7 | return $d->[1]->(); | 
| 1362 |  |  |  |  |  |  | } | 
| 1363 |  |  |  |  |  |  | else { | 
| 1364 | 0 |  |  |  |  |  | my @ds = sort { $DECODERS{$b}[0] <=> $DECODERS{$a}[0] } keys %DECODERS; | 
|  | 0 |  |  |  |  |  |  | 
| 1365 | 0 |  |  |  |  |  | return join ", ", map { "$_;q=$DECODERS{$_}[0]" } @ds; | 
|  | 0 |  |  |  |  |  |  | 
| 1366 |  |  |  |  |  |  | } | 
| 1367 |  |  |  |  |  |  | } | 
| 1368 |  |  |  |  |  |  | } | 
| 1369 |  |  |  |  |  |  |  | 
| 1370 |  |  |  |  |  |  | =head1 EXAMPLES | 
| 1371 |  |  |  |  |  |  |  | 
| 1372 |  |  |  |  |  |  | =head2 Concurrent GET | 
| 1373 |  |  |  |  |  |  |  | 
| 1374 |  |  |  |  |  |  | The C<Future>-returning C<GET> method makes it easy to await multiple URLs at | 
| 1375 |  |  |  |  |  |  | once, by using the L<Future::Utils> C<fmap_void> utility | 
| 1376 |  |  |  |  |  |  |  | 
| 1377 |  |  |  |  |  |  | use Future::AsyncAwait; | 
| 1378 |  |  |  |  |  |  | use Future::Utils qw( fmap_void ); | 
| 1379 |  |  |  |  |  |  |  | 
| 1380 |  |  |  |  |  |  | my @URLs = ( ... ); | 
| 1381 |  |  |  |  |  |  |  | 
| 1382 |  |  |  |  |  |  | my $http = Net::Async::HTTP->new( ... ); | 
| 1383 |  |  |  |  |  |  | $loop->add( $http ); | 
| 1384 |  |  |  |  |  |  |  | 
| 1385 |  |  |  |  |  |  | my $future = fmap_void { | 
| 1386 |  |  |  |  |  |  | my ( $url ) = @_; | 
| 1387 |  |  |  |  |  |  | $http->GET( $url ) | 
| 1388 |  |  |  |  |  |  | ->on_done( sub { | 
| 1389 |  |  |  |  |  |  | my $response = shift; | 
| 1390 |  |  |  |  |  |  | say "$url succeeded: ", $response->code; | 
| 1391 |  |  |  |  |  |  | say "  Content-Type:", $response->content_type; | 
| 1392 |  |  |  |  |  |  | } ) | 
| 1393 |  |  |  |  |  |  | ->on_fail( sub { | 
| 1394 |  |  |  |  |  |  | my $failure = shift; | 
| 1395 |  |  |  |  |  |  | say "$url failed: $failure"; | 
| 1396 |  |  |  |  |  |  | } ); | 
| 1397 |  |  |  |  |  |  | } foreach => \@URLs, | 
| 1398 |  |  |  |  |  |  | concurrent => 5; | 
| 1399 |  |  |  |  |  |  |  | 
| 1400 |  |  |  |  |  |  | await $future; | 
| 1401 |  |  |  |  |  |  |  | 
| 1402 |  |  |  |  |  |  | =cut | 
| 1403 |  |  |  |  |  |  |  | 
| 1404 |  |  |  |  |  |  | =head1 SEE ALSO | 
| 1405 |  |  |  |  |  |  |  | 
| 1406 |  |  |  |  |  |  | =over 4 | 
| 1407 |  |  |  |  |  |  |  | 
| 1408 |  |  |  |  |  |  | =item * | 
| 1409 |  |  |  |  |  |  |  | 
| 1410 |  |  |  |  |  |  | L<http://tools.ietf.org/html/rfc2616> - Hypertext Transfer Protocol -- HTTP/1.1 | 
| 1411 |  |  |  |  |  |  |  | 
| 1412 |  |  |  |  |  |  | =back | 
| 1413 |  |  |  |  |  |  |  | 
| 1414 |  |  |  |  |  |  | =head1 SPONSORS | 
| 1415 |  |  |  |  |  |  |  | 
| 1416 |  |  |  |  |  |  | Parts of this code, or bugfixes to it were paid for by | 
| 1417 |  |  |  |  |  |  |  | 
| 1418 |  |  |  |  |  |  | =over 2 | 
| 1419 |  |  |  |  |  |  |  | 
| 1420 |  |  |  |  |  |  | =item * | 
| 1421 |  |  |  |  |  |  |  | 
| 1422 |  |  |  |  |  |  | SocialFlow L<http://www.socialflow.com> | 
| 1423 |  |  |  |  |  |  |  | 
| 1424 |  |  |  |  |  |  | =item * | 
| 1425 |  |  |  |  |  |  |  | 
| 1426 |  |  |  |  |  |  | Shadowcat Systems L<http://www.shadow.cat> | 
| 1427 |  |  |  |  |  |  |  | 
| 1428 |  |  |  |  |  |  | =item * | 
| 1429 |  |  |  |  |  |  |  | 
| 1430 |  |  |  |  |  |  | NET-A-PORTER L<http://www.net-a-porter.com> | 
| 1431 |  |  |  |  |  |  |  | 
| 1432 |  |  |  |  |  |  | =item * | 
| 1433 |  |  |  |  |  |  |  | 
| 1434 |  |  |  |  |  |  | Cisco L<http://www.cisco.com> | 
| 1435 |  |  |  |  |  |  |  | 
| 1436 |  |  |  |  |  |  | =back | 
| 1437 |  |  |  |  |  |  |  | 
| 1438 |  |  |  |  |  |  | =head1 AUTHOR | 
| 1439 |  |  |  |  |  |  |  | 
| 1440 |  |  |  |  |  |  | Paul Evans <leonerd@leonerd.org.uk> | 
| 1441 |  |  |  |  |  |  |  | 
| 1442 |  |  |  |  |  |  | =cut | 
| 1443 |  |  |  |  |  |  |  | 
| 1444 |  |  |  |  |  |  | 0x55AA; |