File Coverage

blib/lib/HTTP/Tiny.pm
Criterion Covered Total %
statement 629 703 89.4
branch 337 484 69.6
condition 194 302 64.2
subroutine 81 85 95.2
pod 13 15 86.6
total 1254 1589 78.9


line stmt bran cond sub pod time code
1             # vim: ts=4 sts=4 sw=4 et:
2             package HTTP::Tiny;
3 31     31   4222781 use strict;
  31         63  
  31         1364  
4 31     31   199 use warnings;
  31         56  
  31         6149  
5             # ABSTRACT: A small, simple, correct HTTP/1.1 client
6              
7             our $VERSION = '0.092';
8              
9 15     15   100 sub _croak { require Carp; Carp::croak(@_) }
  15         2001  
10              
11             #pod =method new
12             #pod
13             #pod $http = HTTP::Tiny->new( %attributes );
14             #pod
15             #pod This constructor returns a new HTTP::Tiny object. Valid attributes include:
16             #pod
17             #pod =for :list
18             #pod * C — A user-agent string (defaults to 'HTTP-Tiny/$VERSION'). If
19             #pod C — ends in a space character, the default user-agent string is
20             #pod appended.
21             #pod * C — An instance of L — or equivalent class
22             #pod that supports the C and C methods
23             #pod * C — A hashref of default headers to apply to requests
24             #pod * C — The local IP address to bind to
25             #pod * C — Whether to reuse the last connection (if for the same
26             #pod scheme, host and port) (defaults to 1)
27             #pod * C — How many seconds to keep a connection available
28             #pod for after a request (defaults to 0, unlimited)
29             #pod * C — Maximum number of redirects allowed (defaults to 5)
30             #pod * C — Maximum response size in bytes (only when not using a data
31             #pod callback). If defined, requests with responses larger than this will return
32             #pod a 599 status code.
33             #pod * C — URL of a proxy server to use for HTTP connections
34             #pod (default is C<$ENV{http_proxy}> — if set)
35             #pod * C — URL of a proxy server to use for HTTPS connections
36             #pod (default is C<$ENV{https_proxy}> — if set)
37             #pod * C — URL of a generic proxy server for both HTTP and HTTPS
38             #pod connections (default is C<$ENV{all_proxy}> — if set)
39             #pod * C — List of domain suffixes that should not be proxied. Must
40             #pod be a comma-separated string or an array reference. (default is
41             #pod C<$ENV{no_proxy}> —)
42             #pod * C — Request timeout in seconds (default is 60) If a socket open,
43             #pod read or write takes longer than the timeout, the request response status code
44             #pod will be 599.
45             #pod * C — A boolean that indicates whether to validate the TLS/SSL
46             #pod certificate of an C — connection (default is true). Changed from false
47             #pod to true in version 0.083.
48             #pod * C — A hashref of C — options to pass through to
49             #pod L
50             #pod * C<$ENV{PERL_HTTP_TINY_SSL_INSECURE_BY_DEFAULT}> - Changes the default
51             #pod certificate verification behavior to not check server identity if set to 1.
52             #pod Only effective if C is not set. Added in version 0.083.
53             #pod
54             #pod
55             #pod An accessor/mutator method exists for each attribute.
56             #pod
57             #pod Passing an explicit C for C, C or C will
58             #pod prevent getting the corresponding proxies from the environment.
59             #pod
60             #pod Errors during request execution will result in a pseudo-HTTP status code of 599
61             #pod and a reason of "Internal Exception". The content field in the response will
62             #pod contain the text of the error.
63             #pod
64             #pod The C parameter enables a persistent connection, but only to a
65             #pod single destination scheme, host and port. If any connection-relevant
66             #pod attributes are modified via accessor, or if the process ID or thread ID change,
67             #pod the persistent connection will be dropped. If you want persistent connections
68             #pod across multiple destinations, use multiple HTTP::Tiny objects.
69             #pod
70             #pod The C parameter allows you to control how long a
71             #pod keep alive connection will be considered for reuse. By setting this lower
72             #pod than the server keep alive time, this allows you to avoid race conditions where
73             #pod the server closes the connection while preparing to write the request on
74             #pod a reused persistent connection.
75             #pod
76             #pod See L for more on the C and C
77             #pod attributes.
78             #pod
79             #pod =cut
80              
81             my @attributes;
82             BEGIN {
83 31     31   217 @attributes = qw(
84             cookie_jar default_headers http_proxy https_proxy keep_alive
85             local_address max_redirect max_size proxy no_proxy
86             SSL_options verify_SSL
87             );
88 31         88 my %persist_ok = map {; $_ => 1 } qw(
  124         348  
89             cookie_jar default_headers max_redirect max_size
90             );
91 31     31   228 no strict 'refs';
  31         77  
  31         2331  
92 31     31   179 no warnings 'uninitialized';
  31         83  
  31         5870  
93 31         102 for my $accessor ( @attributes ) {
94 372         30197 *{$accessor} = sub {
95             @_ > 1
96             ? do {
97 1 50 33     7 delete $_[0]->{handle} if !$persist_ok{$accessor} && $_[1] ne $_[0]->{$accessor};
98 1         3 $_[0]->{$accessor} = $_[1]
99             }
100 77 100   77   604 : $_[0]->{$accessor};
101 372         1400 };
102             }
103             }
104              
105             sub agent {
106 179     179 0 481 my($self, $agent) = @_;
107 179 100       531 if( @_ > 1 ){
108             $self->{agent} =
109 173 100 100     1105 (defined $agent && $agent =~ / $/) ? $agent . $self->_agent : $agent;
110             }
111 179         631 return $self->{agent};
112             }
113              
114             sub timeout {
115 8     8 0 40 my ($self, $timeout) = @_;
116 8 100       20 if ( @_ > 1 ) {
117 3         8 $self->{timeout} = $timeout;
118 3 100       10 if ($self->{handle}) {
119 2         5 $self->{handle}->timeout($timeout);
120             }
121             }
122 8         39 return $self->{timeout};
123             }
124              
125             sub new {
126 172     172 1 7211187 my($class, %args) = @_;
127              
128             # Support lower case verify_ssl argument, but only if verify_SSL is not
129             # true.
130 172 100       911 if ( exists $args{verify_ssl} ) {
131 7   100     32 $args{verify_SSL} ||= $args{verify_ssl};
132             }
133              
134             my $self = {
135             max_redirect => 5,
136             timeout => defined $args{timeout} ? $args{timeout} : 60,
137             keep_alive => 1,
138             keep_alive_timeout => 0,
139             verify_SSL => defined $args{verify_SSL} ? $args{verify_SSL} : _verify_SSL_default(),
140             no_proxy => $ENV{no_proxy},
141 172 100       1278 };
    100          
142              
143 172         442 bless $self, $class;
144              
145 172 100       604 $class->_validate_cookie_jar( $args{cookie_jar} ) if $args{cookie_jar};
146              
147 170         556 for my $key ( @attributes ) {
148 2040 100       4315 $self->{$key} = $args{$key} if exists $args{$key}
149             }
150              
151 170 100       893 $self->agent( exists $args{agent} ? $args{agent} : $class->_agent );
152              
153 170         644 $self->_set_proxies;
154              
155 169         2757 return $self;
156             }
157              
158             sub _verify_SSL_default {
159 315     315   724 my ($self) = @_;
160             # Check if insecure default certificate verification behaviour has been
161             # changed by the user by setting PERL_HTTP_TINY_SSL_INSECURE_BY_DEFAULT=1
162 315 100 100     4662 return (($ENV{PERL_HTTP_TINY_SSL_INSECURE_BY_DEFAULT} || '') eq '1') ? 0 : 1;
163             }
164              
165             sub _set_proxies {
166 170     170   405 my ($self) = @_;
167              
168             # get proxies from %ENV only if not provided; explicit undef will disable
169             # getting proxies from the environment
170              
171             # generic proxy
172 170 100       499 if (! exists $self->{proxy} ) {
173 167   100     942 $self->{proxy} = $ENV{all_proxy} || $ENV{ALL_PROXY};
174             }
175              
176 170 100       433 if ( defined $self->{proxy} ) {
177 4         16 $self->_split_proxy( 'generic proxy' => $self->{proxy} ); # validate
178             }
179             else {
180 166         340 delete $self->{proxy};
181             }
182              
183             # http proxy
184 170 100       545 if (! exists $self->{http_proxy} ) {
185             # under CGI, bypass HTTP_PROXY as request sets it from Proxy header
186 169 100 100     478 local $ENV{HTTP_PROXY} = ($ENV{CGI_HTTP_PROXY} || "") if $ENV{REQUEST_METHOD};
187 169   100     1138 $self->{http_proxy} = $ENV{http_proxy} || $ENV{HTTP_PROXY} || $self->{proxy};
188             }
189              
190 170 100       463 if ( defined $self->{http_proxy} ) {
191 10         28 $self->_split_proxy( http_proxy => $self->{http_proxy} ); # validate
192 9         23 $self->{_has_proxy}{http} = 1;
193             }
194             else {
195 160         287 delete $self->{http_proxy};
196             }
197              
198             # https proxy
199 169 100       431 if (! exists $self->{https_proxy} ) {
200 168   100     1108 $self->{https_proxy} = $ENV{https_proxy} || $ENV{HTTPS_PROXY} || $self->{proxy};
201             }
202              
203 169 100       403 if ( $self->{https_proxy} ) {
204 6         19 $self->_split_proxy( https_proxy => $self->{https_proxy} ); # validate
205 6         11 $self->{_has_proxy}{https} = 1;
206             }
207             else {
208 163         327 delete $self->{https_proxy};
209             }
210              
211             # Split no_proxy to array reference if not provided as such
212 169 100       579 unless ( ref $self->{no_proxy} eq 'ARRAY' ) {
213             $self->{no_proxy} =
214 166 100       677 (defined $self->{no_proxy}) ? [ split /\s*,\s*/, $self->{no_proxy} ] : [];
215             }
216              
217 169         347 return;
218             }
219              
220             #pod =method get|head|put|post|patch|delete
221             #pod
222             #pod $response = $http->get($url);
223             #pod $response = $http->get($url, \%options);
224             #pod $response = $http->head($url);
225             #pod
226             #pod These methods are shorthand for calling C for the given method. The
227             #pod URL must have unsafe characters escaped and international domain names encoded.
228             #pod See C for valid options and a description of the response.
229             #pod
230             #pod The C field of the response will be true if the status code is 2XX.
231             #pod
232             #pod =cut
233              
234             for my $sub_name ( qw/get head put post patch delete/ ) {
235             my $req_method = uc $sub_name;
236 31     31   245 no strict 'refs';
  31         57  
  31         185465  
237 1 0 0 1 1 46 eval <<"HERE"; ## no critic
  1 100 33 76 1 2  
  1 0 50 2 1 7  
  76 0 100 0 1 33018  
  76 50 100 2 1 356  
  73 50 100 8 1 650  
  2   0     1541  
  2   33     9  
  2   50     15  
  0   0     0  
  0   0     0  
  0   0     0  
  2   33     83  
  2   33     12  
  2   50     9  
  8   33     501  
  8   33     67  
  8   50     46  
238             sub $sub_name {
239             my (\$self, \$url, \$args) = \@_;
240             \@_ == 2 || (\@_ == 3 && ref \$args eq 'HASH')
241             or _croak(q/Usage: \$http->$sub_name(URL, [HASHREF])/ . "\n");
242             return \$self->request('$req_method', \$url, \$args || {});
243             }
244             HERE
245             }
246              
247             #pod =method post_form
248             #pod
249             #pod $response = $http->post_form($url, $form_data);
250             #pod $response = $http->post_form($url, $form_data, \%options);
251             #pod
252             #pod This method executes a C request and sends the key/value pairs from a
253             #pod form data hash or array reference to the given URL with a C of
254             #pod C. If data is provided as an array
255             #pod reference, the order is preserved; if provided as a hash reference, the terms
256             #pod are sorted by key for consistency. See documentation for the
257             #pod C method for details on the encoding.
258             #pod
259             #pod The URL must have unsafe characters escaped and international domain names
260             #pod encoded. See C for valid options and a description of the response.
261             #pod Any C header or content in the options hashref will be ignored.
262             #pod
263             #pod The C field of the response will be true if the status code is 2XX.
264             #pod
265             #pod =cut
266              
267             sub post_form {
268 7     7 1 1576 my ($self, $url, $data, $args) = @_;
269 7 50 33     28 (@_ == 3 || @_ == 4 && ref $args eq 'HASH')
      66        
270             or _croak(q/Usage: $http->post_form(URL, DATAREF, [HASHREF])/ . "\n");
271              
272 7         13 my $headers = {};
273 7 100       11 while ( my ($key, $value) = each %{$args->{headers} || {}} ) {
  8         49  
274 1         3 $headers->{lc $key} = $value;
275             }
276              
277 7         30 return $self->request('POST', $url, {
278             # Any existing 'headers' key in $args will be overridden with a
279             # normalized version below.
280             %$args,
281             content => $self->www_form_urlencode($data),
282             headers => {
283             %$headers,
284             'content-type' => 'application/x-www-form-urlencoded'
285             },
286             }
287             );
288             }
289              
290             #pod =method mirror
291             #pod
292             #pod $response = $http->mirror($url, $file, \%options)
293             #pod if ( $response->{success} ) {
294             #pod print "$file is up to date\n";
295             #pod }
296             #pod
297             #pod Executes a C request for the URL and saves the response body to the file
298             #pod name provided. The URL must have unsafe characters escaped and international
299             #pod domain names encoded. If the file already exists, the request will include an
300             #pod C header with the modification timestamp of the file. You
301             #pod may specify a different C header yourself in the C<<
302             #pod $options->{headers} >> hash.
303             #pod
304             #pod The C field of the response will be true if the status code is 2XX
305             #pod or if the status code is 304 (unmodified).
306             #pod
307             #pod If the file was modified and the server response includes a properly
308             #pod formatted C header, the file modification time will
309             #pod be updated accordingly.
310             #pod
311             #pod =cut
312              
313             sub mirror {
314 9     9 1 2239 my ($self, $url, $file, $args) = @_;
315 9 100 100     55 @_ == 3 || (@_ == 4 && ref $args eq 'HASH')
      100        
316             or _croak(q/Usage: $http->mirror(URL, FILE, [HASHREF])/ . "\n");
317              
318 5 100       15 if ( exists $args->{headers} ) {
319 1         20 my $headers = {};
320 1 50       3 while ( my ($key, $value) = each %{$args->{headers} || {}} ) {
  2         15  
321 1         7 $headers->{lc $key} = $value;
322             }
323 1         3 $args->{headers} = $headers;
324             }
325              
326 5 100 66     130 if ( -e $file and my $mtime = (stat($file))[9] ) {
327 3   66     28 $args->{headers}{'if-modified-since'} ||= $self->_http_date($mtime);
328             }
329 5         70 my $tempfile = $file . int(rand(2**31));
330              
331 5         55 require Fcntl;
332 5 50       2858 sysopen my $fh, $tempfile, Fcntl::O_CREAT()|Fcntl::O_EXCL()|Fcntl::O_WRONLY()
333             or _croak(qq/Error: Could not create temporary file $tempfile for downloading: $!\n/);
334 5         27 binmode $fh;
335 5     3   84 $args->{data_callback} = sub { print {$fh} $_[0] };
  3         4  
  3         10  
336 5         31 my $response = $self->request('GET', $url, $args);
337 5 50       168 close $fh
338             or _croak(qq/Error: Caught error closing temporary file $tempfile: $!\n/);
339              
340 5 100       18 if ( $response->{success} ) {
341 3 50       301 rename $tempfile, $file
342             or _croak(qq/Error replacing $file with $tempfile: $!\n/);
343 3         17 my $lm = $response->{headers}{'last-modified'};
344 3 50 33     22 if ( $lm and my $mtime = $self->_parse_http_date($lm) ) {
345 3         108 utime $mtime, $mtime, $file;
346             }
347             }
348 5   100     28 $response->{success} ||= $response->{status} eq '304';
349 5         221 unlink $tempfile;
350 5         54 return $response;
351             }
352              
353             #pod =method request
354             #pod
355             #pod $response = $http->request($method, $url);
356             #pod $response = $http->request($method, $url, \%options);
357             #pod
358             #pod Executes an HTTP request of the given method type ('GET', 'HEAD', 'POST',
359             #pod 'PUT', etc.) on the given URL. The URL must have unsafe characters escaped and
360             #pod international domain names encoded.
361             #pod
362             #pod B: Method names are B per the HTTP/1.1 specification.
363             #pod Don't use C when you really want C. See L for
364             #pod how this applies to redirection.
365             #pod
366             #pod If the URL includes a "user:password" stanza, they will be used for Basic-style
367             #pod authorization headers. (Authorization headers will not be included in a
368             #pod redirected request.) For example:
369             #pod
370             #pod $http->request('GET', 'http://Aladdin:open sesame@example.com/');
371             #pod
372             #pod If the "user:password" stanza contains reserved characters, they must
373             #pod be percent-escaped:
374             #pod
375             #pod $http->request('GET', 'http://john%40example.com:password@example.com/');
376             #pod
377             #pod A hashref of options may be appended to modify the request.
378             #pod
379             #pod Valid options are:
380             #pod
381             #pod =for :list
382             #pod * C
383             #pod A hashref containing headers to include with the request. If the value for
384             #pod a header is an array reference, the header will be output multiple times with
385             #pod each value in the array. These headers over-write any default headers.
386             #pod * C
387             #pod A scalar to include as the body of the request OR a code reference
388             #pod that will be called iteratively to produce the body of the request
389             #pod * C
390             #pod A code reference that will be called if it exists to provide a hashref
391             #pod of trailing headers (only used with chunked transfer-encoding)
392             #pod * C
393             #pod A code reference that will be called for each chunks of the response
394             #pod body received.
395             #pod * C
396             #pod Override host resolution and force all connections to go only to a
397             #pod specific peer address, regardless of the URL of the request. This will
398             #pod include any redirections! This options should be used with extreme
399             #pod caution (e.g. debugging or very special circumstances). It can be given as
400             #pod either a scalar or a code reference that will receive the hostname and
401             #pod whose response will be taken as the address.
402             #pod
403             #pod The C header is generated from the URL in accordance with RFC 2616. It
404             #pod is a fatal error to specify C in the C option. Other headers
405             #pod may be ignored or overwritten if necessary for transport compliance.
406             #pod
407             #pod If the C option is a code reference, it will be called iteratively
408             #pod to provide the content body of the request. It should return the empty
409             #pod string or undef when the iterator is exhausted.
410             #pod
411             #pod If the C option is the empty string, no C or
412             #pod C headers will be generated.
413             #pod
414             #pod If the C option is provided, it will be called iteratively until
415             #pod the entire response body is received. The first argument will be a string
416             #pod containing a chunk of the response body, the second argument will be the
417             #pod in-progress response hash reference, as described below. (This allows
418             #pod customizing the action of the callback based on the C or C
419             #pod received prior to the content body.)
420             #pod
421             #pod Content data in the request/response is handled as "raw bytes". Any
422             #pod encoding/decoding (with associated headers) are the responsibility of the
423             #pod caller.
424             #pod
425             #pod The C method returns a hashref containing the response. The hashref
426             #pod will have the following keys:
427             #pod
428             #pod =for :list
429             #pod * C
430             #pod Boolean indicating whether the operation returned a 2XX status code
431             #pod * C
432             #pod URL that provided the response. This is the URL of the request unless
433             #pod there were redirections, in which case it is the last URL queried
434             #pod in a redirection chain
435             #pod * C
436             #pod The HTTP status code of the response
437             #pod * C
438             #pod The response phrase returned by the server
439             #pod * C
440             #pod The body of the response. If the response does not have any content
441             #pod or if a data callback is provided to consume the response body,
442             #pod this will be the empty string
443             #pod * C
444             #pod A hashref of header fields. All header field names will be normalized
445             #pod to be lower case. If a header is repeated, the value will be an arrayref;
446             #pod it will otherwise be a scalar string containing the value
447             #pod * C -
448             #pod If this field exists, it is the protocol of the response
449             #pod such as HTTP/1.0 or HTTP/1.1
450             #pod * C
451             #pod If this field exists, it is an arrayref of response hash references from
452             #pod redirects in the same order that redirections occurred. If it does
453             #pod not exist, then no redirections occurred.
454             #pod
455             #pod On an error during the execution of the request, the C field will
456             #pod contain 599, and the C field will contain the text of the error.
457             #pod
458             #pod =cut
459              
460             my %idempotent = map { $_ => 1 } qw/GET HEAD PUT DELETE OPTIONS TRACE/;
461              
462             sub request {
463 149     149 1 17912 my ($self, $method, $url, $args) = @_;
464 149 100 100     1113 @_ == 3 || (@_ == 4 && ref $args eq 'HASH')
      100        
465             or _croak(q/Usage: $http->request(METHOD, URL, [HASHREF])/ . "\n");
466 145   100     485 $args ||= {}; # we keep some state in this during _request
467              
468             # RFC 2616 Section 8.1.4 mandates a single retry on broken socket
469 145         240 my $response;
470 145         506 for ( 0 .. 1 ) {
471 145         383 $response = eval { $self->_request($method, $url, $args) };
  145         570  
472 145 50 66     7347 last unless $@ && $idempotent{$method}
      33        
473             && $@ =~ m{^(?:Socket closed|Unexpected end|SSL read error)};
474             }
475              
476 145 100       475 if (my $e = $@) {
477             # maybe we got a response hash thrown from somewhere deep
478 20 0 33     82 if ( ref $e eq 'HASH' && exists $e->{status} ) {
479 0 0       0 $e->{redirects} = delete $args->{_redirects} if @{ $args->{_redirects} || []};
  0 0       0  
480 0         0 return $e;
481             }
482              
483             # otherwise, stringify it
484 20         54 $e = "$e";
485             $response = {
486             url => $url,
487             success => q{},
488             status => 599,
489             reason => 'Internal Exception',
490             content => $e,
491             headers => {
492             'content-type' => 'text/plain',
493             'content-length' => length $e,
494             },
495 20 100       176 ( @{$args->{_redirects} || []} ? (redirects => delete $args->{_redirects}) : () ),
  20 50       396  
496             };
497             }
498 145         707 return $response;
499             }
500              
501             #pod =method www_form_urlencode
502             #pod
503             #pod $params = $http->www_form_urlencode( $data );
504             #pod $response = $http->get("http://example.com/query?$params");
505             #pod
506             #pod This method converts the key/value pairs from a data hash or array reference
507             #pod into a C string. The keys and values from the data
508             #pod reference will be UTF-8 encoded and escaped per RFC 3986. If a value is an
509             #pod array reference, the key will be repeated with each of the values of the array
510             #pod reference. If data is provided as a hash reference, the key/value pairs in the
511             #pod resulting string will be sorted by key and value for consistent ordering.
512             #pod
513             #pod =cut
514              
515             sub www_form_urlencode {
516 7     7 1 13 my ($self, $data) = @_;
517 7 50 33     38 (@_ == 2 && ref $data)
518             or _croak(q/Usage: $http->www_form_urlencode(DATAREF)/ . "\n");
519 7 50 66     27 (ref $data eq 'HASH' || ref $data eq 'ARRAY')
520             or _croak("form data must be a hash or array reference\n");
521              
522             my @params
523             = ref $data eq 'HASH'
524 7 100       34 ? map { ($_ => $data->{$_}) } sort keys %$data
  9         26  
525             : @$data;
526 7 50       20 @params % 2 == 0
527             or _croak("form data reference must have an even number of terms\n");
528              
529 7         13 my @terms;
530 7         17 while( @params ) {
531 21         44 my ($key, $value) = splice(@params, 0, 2);
532 21 100       121 _croak("form data keys must not be undef")
533             if !defined($key);
534 20 100       44 if ( ref $value eq 'ARRAY' ) {
535 2         6 unshift @params, map { $key => $_ } @$value;
  4         16  
536             }
537             else {
538 18         31 push @terms, join("=", map { $self->_uri_escape($_) } $key, $value);
  36         70  
539             }
540             }
541              
542 6         42 return join("&", @terms);
543             }
544              
545             #pod =method can_ssl
546             #pod
547             #pod $ok = HTTP::Tiny->can_ssl;
548             #pod ($ok, $why) = HTTP::Tiny->can_ssl;
549             #pod ($ok, $why) = $http->can_ssl;
550             #pod
551             #pod Indicates if SSL support is available. When called as a class object, it
552             #pod checks for the correct version of L and L.
553             #pod When called as an object methods, if C is true or if C
554             #pod is set in C, it checks that a CA file is available.
555             #pod
556             #pod In scalar context, returns a boolean indicating if SSL is available.
557             #pod In list context, returns the boolean and a (possibly multi-line) string of
558             #pod errors indicating why SSL isn't available.
559             #pod
560             #pod =cut
561              
562             sub can_ssl {
563 36     36 1 643667 my ($self) = @_;
564              
565 36         110 my($ok, $reason) = (1, '');
566              
567             # Need IO::Socket::SSL 1.968 for default_ca()
568 36         388 local @INC = @INC;
569 36 50       205 pop @INC if $INC[-1] eq '.';
570 36 50       101 unless (eval {require IO::Socket::SSL; IO::Socket::SSL->VERSION(1.968)}) {
  36         2311  
  36         172594  
571 0         0 $ok = 0;
572 0         0 $reason .= qq/IO::Socket::SSL 1.968 or later must be installed for https support\n/;
573             }
574              
575             # Need Net::SSLeay 1.49 for MODE_AUTO_RETRY
576 36 50       95 unless (eval {require Net::SSLeay; Net::SSLeay->VERSION(1.49)}) {
  36         180  
  36         1539  
577 0         0 $ok = 0;
578 0         0 $reason .= qq/Net::SSLeay 1.49 or later must be installed for https support\n/;
579             }
580              
581             # If an object, check that SSL config lets us get a CA if necessary
582 36 50 33     175 if ( ref($self) && ( $self->{verify_SSL} || $self->{SSL_options}{SSL_verify_mode} ) ) {
      66        
583             my $handle = HTTP::Tiny::Handle->new(
584             SSL_options => $self->{SSL_options},
585             verify_SSL => $self->{verify_SSL},
586 3         17 );
587 3 100       6 unless ( eval { $handle->_find_CA; 1 } ) {
  3         12  
  2         7  
588 1         2 $ok = 0;
589 1         4 $reason .= "$@";
590             }
591             }
592              
593 36 100       293 wantarray ? ($ok, $reason) : $ok;
594             }
595              
596             #pod =method connected
597             #pod
598             #pod $host = $http->connected;
599             #pod ($host, $port) = $http->connected;
600             #pod
601             #pod Indicates if a connection to a peer is being kept alive, per the C
602             #pod option.
603             #pod
604             #pod In scalar context, returns the peer host and port, joined with a colon, or
605             #pod C (if no peer is connected).
606             #pod In list context, returns the peer host and port or an empty list (if no peer
607             #pod is connected).
608             #pod
609             #pod B: This method cannot reliably be used to discover whether the remote
610             #pod host has closed its end of the socket.
611             #pod
612             #pod =cut
613              
614             sub connected {
615 0     0 1 0 my ($self) = @_;
616              
617 0 0       0 if ( $self->{handle} ) {
618 0         0 return $self->{handle}->connected;
619             }
620 0         0 return;
621             }
622              
623             #--------------------------------------------------------------------------#
624             # private methods
625             #--------------------------------------------------------------------------#
626              
627             my %DefaultPort = (
628             http => 80,
629             https => 443,
630             );
631              
632             sub _agent {
633 172   66 172   851 my $class = ref($_[0]) || $_[0];
634 172         1055 (my $default_agent = $class) =~ s{::}{-}g;
635 172         2037 my $version = $class->VERSION;
636 172 50       962 $default_agent .= "/$version" if defined $version;
637 172         778 return $default_agent;
638             }
639              
640             sub _request {
641 158     158   395 my ($self, $method, $url, $args) = @_;
642              
643 158         706 my ($scheme, $host, $port, $path_query, $auth) = $self->_split_url($url);
644              
645 158 100 100     643 if ($scheme ne 'http' && $scheme ne 'https') {
646 1         7 die(qq/Unsupported URL scheme '$scheme'\n/);
647             }
648              
649             my $request = {
650             method => $method,
651             scheme => $scheme,
652             host => $host,
653             port => $port,
654 157 100       1777 host_port => ($port == $DefaultPort{$scheme} ? $host : "$host:$port"),
655             uri => $path_query,
656             headers => {},
657             };
658              
659 157   33     724 my $peer = $args->{peer} || $host;
660              
661             # Allow 'peer' to be a coderef.
662 157 50       475 if ('CODE' eq ref $peer) {
663 0         0 $peer = $peer->($host);
664             }
665              
666             # We remove the cached handle so it is not reused in the case of redirect.
667             # If all is well, it will be recached at the end of _request. We only
668             # reuse for the same scheme, host and port
669 157         406 my $handle = delete $self->{handle};
670 157 100       436 if ( $handle ) {
671 16 100       39 unless ( $handle->can_reuse( $scheme, $host, $port, $peer ) ) {
672 11         81 $handle->close;
673 11         378 undef $handle;
674             }
675             }
676 157   100     823 $handle ||= $self->_open_handle( $request, $scheme, $host, $port, $peer );
677              
678 143         1171 $self->_prepare_headers_and_cb($request, $args, $url, $auth);
679 142         597 $handle->write_request($request);
680              
681 141         2544 my $response;
682 143         507 do { $response = $handle->read_response_header }
683 141         360 until (substr($response->{status},0,1) ne '1');
684              
685 139 100       571 $self->_update_cookie_jar( $url, $response ) if $self->{cookie_jar};
686 139         605 my @redir_args = $self->_maybe_redirect($request, $response, $args);
687              
688 139         224 my $known_message_length;
689 139 100 100     724 if ($method eq 'HEAD' || $response->{status} =~ /^[23]04/) {
690             # response has no message body
691 2         5 $known_message_length = 1;
692             }
693             else {
694             # Ignore any data callbacks during redirection.
695 137 100       296 my $cb_args = @redir_args ? +{} : $args;
696 137         421 my $data_cb = $self->_prepare_data_cb($response, $cb_args);
697 137         438 $known_message_length = $handle->read_body($data_cb, $response);
698             }
699              
700 138 100 66     677 if ( $self->{keep_alive}
      100        
      100        
      100        
      100        
701             && $handle->connected
702             && $known_message_length
703             && $response->{protocol} eq 'HTTP/1.1'
704             && ($response->{headers}{connection} || '') ne 'close'
705             ) {
706 43         2601 $handle->_update_last_used();
707 43         128 $self->{handle} = $handle;
708             }
709             else {
710 95         744 $handle->close;
711             }
712              
713 138         2633 $response->{success} = substr( $response->{status}, 0, 1 ) eq '2';
714 138         417 $response->{url} = $url;
715              
716             # Push the current response onto the stack of redirects if redirecting.
717 138 100       341 if (@redir_args) {
718 13         28 push @{$args->{_redirects}}, $response;
  13         43  
719 13         65 return $self->_request(@redir_args, $args);
720             }
721              
722             # Copy the stack of redirects into the response before returning.
723             $response->{redirects} = delete $args->{_redirects}
724 125 100       196 if @{$args->{_redirects}};
  125         454  
725 125         1741 return $response;
726             }
727              
728             sub _open_handle {
729 152     152   533 my ($self, $request, $scheme, $host, $port, $peer) = @_;
730              
731             my $handle = HTTP::Tiny::Handle->new(
732             timeout => $self->{timeout},
733             SSL_options => $self->{SSL_options},
734             verify_SSL => $self->{verify_SSL},
735             local_address => $self->{local_address},
736             keep_alive => $self->{keep_alive},
737             keep_alive_timeout => $self->{keep_alive_timeout}
738 152         1692 );
739              
740 152 50       696 require Time::HiRes if $self->{keep_alive_timeout} > 0;
741              
742 152 100 66     600 if ($self->{_has_proxy}{$scheme} && ! grep { $host =~ /\Q$_\E$/ } @{$self->{no_proxy}}) {
  0         0  
  2         12  
743 2         8 return $self->_proxy_connect( $request, $handle );
744             }
745             else {
746 150         651 return $handle->connect($scheme, $host, $port, $peer);
747             }
748             }
749              
750             sub _proxy_connect {
751 2     2   7 my ($self, $request, $handle) = @_;
752              
753 2         4 my @proxy_vars;
754 2 50       8 if ( $request->{scheme} eq 'https' ) {
755 0 0       0 _croak(qq{No https_proxy defined}) unless $self->{https_proxy};
756 0         0 @proxy_vars = $self->_split_proxy( https_proxy => $self->{https_proxy} );
757 0 0       0 if ( $proxy_vars[0] eq 'https' ) {
758 0         0 _croak(qq{Can't proxy https over https: $request->{uri} via $self->{https_proxy}});
759             }
760             }
761             else {
762 2 50       8 _croak(qq{No http_proxy defined}) unless $self->{http_proxy};
763 2         9 @proxy_vars = $self->_split_proxy( http_proxy => $self->{http_proxy} );
764             }
765              
766 2         8 my ($p_scheme, $p_host, $p_port, $p_auth) = @proxy_vars;
767              
768 2 100 66     13 if ( length $p_auth && ! defined $request->{headers}{'proxy-authorization'} ) {
769 1         5 $self->_add_basic_auth_header( $request, 'proxy-authorization' => $p_auth );
770             }
771              
772 2         15 $handle->connect($p_scheme, $p_host, $p_port, $p_host);
773              
774 2 50       12 if ($request->{scheme} eq 'https') {
775 0         0 $self->_create_proxy_tunnel( $request, $handle );
776             }
777             else {
778             # non-tunneled proxy requires absolute URI
779 2         11 $request->{uri} = "$request->{scheme}://$request->{host_port}$request->{uri}";
780             }
781              
782 2         14 return $handle;
783             }
784              
785             sub _split_proxy {
786 22     22   47 my ($self, $type, $proxy) = @_;
787              
788 22         31 my ($scheme, $host, $port, $path_query, $auth) = eval { $self->_split_url($proxy) };
  22         51  
789              
790 22 50 66     152 unless(
      66        
      33        
      33        
791             defined($scheme) && length($scheme) && length($host) && length($port)
792             && $path_query eq '/'
793             ) {
794 1         3 _croak(qq{$type URL must be in format http[s]://[auth@]:/\n});
795             }
796              
797 21         41 return ($scheme, $host, $port, $auth);
798             }
799              
800             sub _create_proxy_tunnel {
801 0     0   0 my ($self, $request, $handle) = @_;
802              
803 0         0 $handle->_assert_ssl;
804              
805             my $agent = exists($request->{headers}{'user-agent'})
806 0 0       0 ? $request->{headers}{'user-agent'} : $self->{agent};
807              
808 0         0 my $connect_request = {
809             method => 'CONNECT',
810             uri => "$request->{host}:$request->{port}",
811             headers => {
812             host => "$request->{host}:$request->{port}",
813             'user-agent' => $agent,
814             }
815             };
816              
817 0 0       0 if ( $request->{headers}{'proxy-authorization'} ) {
818             $connect_request->{headers}{'proxy-authorization'} =
819 0         0 delete $request->{headers}{'proxy-authorization'};
820             }
821              
822 0         0 $handle->write_request($connect_request);
823 0         0 my $response;
824 0         0 do { $response = $handle->read_response_header }
825 0         0 until (substr($response->{status},0,1) ne '1');
826              
827             # if CONNECT failed, throw the response so it will be
828             # returned from the original request() method;
829 0 0       0 unless (substr($response->{status},0,1) eq '2') {
830 0         0 die $response;
831             }
832              
833             # tunnel established, so start SSL handshake
834 0         0 $handle->start_ssl( $request->{host} );
835              
836 0         0 return;
837             }
838              
839             sub _prepare_headers_and_cb {
840 143     143   458 my ($self, $request, $args, $url, $auth) = @_;
841              
842 143         580 for ($self->{default_headers}, $args->{headers}) {
843 286 100       819 next unless defined;
844 25         186 while (my ($k, $v) = each %$_) {
845 32         115 $request->{headers}{lc $k} = $v;
846 32         164 $request->{header_case}{lc $k} = $k;
847             }
848             }
849              
850 143 100       473 if (exists $request->{headers}{'host'}) {
851 1         11 die(qq/The 'Host' header must not be provided as header option\n/);
852             }
853              
854 142         461 $request->{headers}{'host'} = $request->{host_port};
855 142   33     815 $request->{headers}{'user-agent'} ||= $self->{agent};
856             $request->{headers}{'connection'} = "close"
857 142 100       526 unless $self->{keep_alive};
858              
859             # Some servers error on an empty-body PUT/POST without a content-length
860 142 100 100     735 if ( $request->{method} eq 'PUT' || $request->{method} eq 'POST' ) {
861 49 100 100     171 if (!defined($args->{content}) || !length($args->{content}) ) {
862 19         34 $request->{headers}{'content-length'} = 0;
863             }
864             }
865              
866 142 100       367 if ( defined $args->{content} ) {
867 31 100       91 if ( ref $args->{content} eq 'CODE' ) {
    100          
868 5 50 33     18 if ( exists $request->{'content-length'} && $request->{'content-length'} == 0 ) {
869 0     0   0 $request->{cb} = sub { "" };
  0         0  
870             }
871             else {
872 5   50     18 $request->{headers}{'content-type'} ||= "application/octet-stream";
873             $request->{headers}{'transfer-encoding'} = 'chunked'
874             unless exists $request->{headers}{'content-length'}
875 5 50 66     26 || $request->{headers}{'transfer-encoding'};
876 5         13 $request->{cb} = $args->{content};
877             }
878             }
879             elsif ( length $args->{content} ) {
880 25         37 my $content = $args->{content};
881 25 50       129 if ( "$]" >= 5.008 ) {
882 25 50       73 utf8::downgrade($content, 1)
883             or die(qq/Wide character in request message body\n/);
884             }
885 25   100     87 $request->{headers}{'content-type'} ||= "application/octet-stream";
886             $request->{headers}{'content-length'} = length $content
887             unless $request->{headers}{'content-length'}
888 25 50 66     107 || $request->{headers}{'transfer-encoding'};
889 25     50   122 $request->{cb} = sub { substr $content, 0, length $content, '' };
  50         140  
890             }
891             $request->{trailer_cb} = $args->{trailer_callback}
892 31 100       83 if ref $args->{trailer_callback} eq 'CODE';
893             }
894              
895             ### If we have a cookie jar, then maybe add relevant cookies
896 142 100       419 if ( $self->{cookie_jar} ) {
897 17         43 my $cookies = $self->cookie_jar->cookie_header( $url );
898 17 100       251 $request->{headers}{cookie} = $cookies if length $cookies;
899             }
900              
901             # if we have Basic auth parameters, add them
902 142 100 100     380 if ( length $auth && ! defined $request->{headers}{authorization} ) {
903 4         13 $self->_add_basic_auth_header( $request, 'authorization' => $auth );
904             }
905              
906 142         287 return;
907             }
908              
909             sub _add_basic_auth_header {
910 5     5   13 my ($self, $request, $header, $auth) = @_;
911 5         1683 require MIME::Base64;
912 5         2223 $request->{headers}{$header} =
913             "Basic " . MIME::Base64::encode_base64($auth, "");
914 5         13 return;
915             }
916              
917             sub _prepare_data_cb {
918 137     137   307 my ($self, $response, $args) = @_;
919 137         318 my $data_cb = $args->{data_callback};
920 137         325 $response->{content} = '';
921              
922 137 100 100     410 if (!$data_cb || $response->{status} !~ /^2/) {
923 133 100       307 if (defined $self->{max_size}) {
924             $data_cb = sub {
925 1     1   5 $_[1]->{content} .= $_[0];
926             die(qq/Size of response body exceeds the maximum allowed of $self->{max_size}\n/)
927 1 50       29 if length $_[1]->{content} > $self->{max_size};
928 1         9 };
929             }
930             else {
931 132     154   738 $data_cb = sub { $_[1]->{content} .= $_[0] };
  154         3961  
932             }
933             }
934 137         401 return $data_cb;
935             }
936              
937             sub _update_cookie_jar {
938 17     17   40 my ($self, $url, $response) = @_;
939              
940 17         36 my $cookies = $response->{headers}->{'set-cookie'};
941 17 100       40 return unless defined $cookies;
942              
943 15 100       40 my @cookies = ref $cookies ? @$cookies : $cookies;
944              
945 15         54 $self->cookie_jar->add( $url, $_ ) for @cookies;
946              
947 15         431 return;
948             }
949              
950             sub _validate_cookie_jar {
951 9     9   25 my ($class, $jar) = @_;
952              
953             # duck typing
954 9         22 for my $method ( qw/add cookie_header/ ) {
955 17 100 66     145 _croak(qq/Cookie jar must provide the '$method' method\n/)
956             unless ref($jar) && ref($jar)->can($method);
957             }
958              
959 7         17 return;
960             }
961              
962             sub _maybe_redirect {
963 139     139   341 my ($self, $request, $response, $args) = @_;
964 139         262 my $headers = $response->{headers};
965 139         529 my ($status, $method) = ($response->{status}, $request->{method});
966 139   100     763 $args->{_redirects} ||= [];
967              
968 139 100 100     857 if (($status eq '303' or ($status =~ /^30[1278]/ && $method =~ /^GET|HEAD$/))
      66        
      66        
969             and $headers->{location}
970 15         72 and @{$args->{_redirects}} < $self->{max_redirect}
971             ) {
972             my $location = ($headers->{location} =~ /^\//)
973             ? "$request->{scheme}://$request->{host_port}$headers->{location}"
974 13 100       73 : $headers->{location} ;
975 13 100       113 return (($status eq '303' ? 'GET' : $method), $location);
976             }
977 126         340 return;
978             }
979              
980             sub _split_url {
981 194     194   326478 my $url = pop;
982              
983             # URI regex adapted from the URI module
984 194 100       1898 my ($scheme, $host, $path_query) = $url =~ m<\A([^:/?#]+)://([^/?#]*)([^#]*)>
985             or die(qq/Cannot parse URL: '$url'\n/);
986              
987 193         1079 $scheme = lc $scheme;
988 193 100       748 $path_query = "/$path_query" unless $path_query =~ m<\A/>;
989              
990 193         419 my $auth = '';
991 193 100       826 if ( (my $i = index $host, '@') != -1 ) {
992             # user:pass@host
993 12         31 $auth = substr $host, 0, $i, ''; # take up to the @ for auth
994 12         21 substr $host, 0, 1, ''; # knock the @ off the host
995              
996             # userinfo might be percent escaped, so recover real auth info
997 12         33 $auth =~ s/%([0-9A-Fa-f]{2})/chr(hex($1))/eg;
  1         8  
998             }
999 193 100 100     1230 my $port = $host =~ s/:(\d*)\z// && length $1 ? $1
    100          
    100          
1000             : $scheme eq 'http' ? 80
1001             : $scheme eq 'https' ? 443
1002             : undef;
1003              
1004 193 100       1242 return ($scheme, (length $host ? lc $host : "localhost") , $port, $path_query, $auth);
1005             }
1006              
1007             # Date conversions adapted from HTTP::Date
1008             my $DoW = "Sun|Mon|Tue|Wed|Thu|Fri|Sat";
1009             my $MoY = "Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec";
1010             sub _http_date {
1011 3     3   203577 my ($sec, $min, $hour, $mday, $mon, $year, $wday) = gmtime($_[1]);
1012 3         40 return sprintf("%s, %02d %s %04d %02d:%02d:%02d GMT",
1013             substr($DoW,$wday*4,3),
1014             $mday, substr($MoY,$mon*4,3), $year+1900,
1015             $hour, $min, $sec
1016             );
1017             }
1018              
1019             sub _parse_http_date {
1020 9     9   2902 my ($self, $str) = @_;
1021 9         1405 require Time::Local;
1022 9         3293 my @tl_parts;
1023 9 100       469 if ($str =~ /^[SMTWF][a-z]+, +(\d{1,2}) ($MoY) +(\d\d\d\d) +(\d\d):(\d\d):(\d\d) +GMT$/) {
    100          
    50          
1024 5         54 @tl_parts = ($6, $5, $4, $1, (index($MoY,$2)/4), $3);
1025             }
1026             elsif ($str =~ /^[SMTWF][a-z]+, +(\d\d)-($MoY)-(\d{2,4}) +(\d\d):(\d\d):(\d\d) +GMT$/ ) {
1027 2         15 @tl_parts = ($6, $5, $4, $1, (index($MoY,$2)/4), $3);
1028             }
1029             elsif ($str =~ /^[SMTWF][a-z]+ +($MoY) +(\d{1,2}) +(\d\d):(\d\d):(\d\d) +(?:[^0-9]+ +)?(\d\d\d\d)$/ ) {
1030 2         14 @tl_parts = ($5, $4, $3, $2, (index($MoY,$1)/4), $6);
1031             }
1032 9         18 return eval {
1033 9 50       36 my $t = @tl_parts ? Time::Local::timegm(@tl_parts) : -1;
1034 9 50       412 $t < 0 ? undef : $t;
1035             };
1036             }
1037              
1038             # URI escaping adapted from URI::Escape
1039             # c.f. http://www.w3.org/TR/html4/interact/forms.html#h-17.13.4.1
1040             # perl 5.6 ready UTF-8 encoding adapted from JSON::PP
1041             my %escapes = map { chr($_) => sprintf("%%%02X", $_) } 0..255;
1042             $escapes{' '}="+";
1043             my $unsafe_char = qr/[^A-Za-z0-9\-\._~]/;
1044              
1045             sub _uri_escape {
1046 36     36   57 my ($self, $str) = @_;
1047 36 100       61 return "" if !defined $str;
1048 34 50       108 if ( "$]" >= 5.008 ) {
1049 34         59 utf8::encode($str);
1050             }
1051             else {
1052             $str = pack("U*", unpack("C*", $str)) # UTF-8 encode a byte string
1053 31 0   31   21304 if ( length $str == do { use bytes; length $str } );
  31         14913  
  31         2068  
  0         0  
  0         0  
1054 0         0 $str = pack("C*", unpack("C*", $str)); # clear UTF-8 flag
1055             }
1056 34         260 $str =~ s/($unsafe_char)/$escapes{$1}/g;
1057 34         117 return $str;
1058             }
1059              
1060             package
1061             HTTP::Tiny::Handle; # hide from PAUSE/indexers
1062 31     31   5545 use strict;
  31         2847  
  31         4288  
1063 31     31   149 use warnings;
  31         57  
  31         4248  
1064              
1065 31     31   16179 use Errno qw[EINTR EPIPE];
  31         49520  
  31         4893  
1066 31     31   15784 use IO::Socket qw[SOCK_STREAM];
  31         522516  
  31         158  
1067 31     31   9069 use Socket qw[SOL_SOCKET SO_KEEPALIVE TCP_NODELAY IPPROTO_TCP];
  31         63  
  31         206369  
1068              
1069             # PERL_HTTP_TINY_IPV4_ONLY is a private environment variable to force old
1070             # behavior if someone is unable to boostrap CPAN from a new perl install; it is
1071             # not intended for general, per-client use and may be removed in the future
1072             my $SOCKET_CLASS =
1073             $ENV{PERL_HTTP_TINY_IPV4_ONLY} ? 'IO::Socket::INET' :
1074             eval { require IO::Socket::IP; IO::Socket::IP->VERSION(0.32) } ? 'IO::Socket::IP' :
1075             'IO::Socket::INET';
1076              
1077             sub BUFSIZE () { 32768 } ## no critic
1078              
1079             my $Printable = sub {
1080             local $_ = shift;
1081             s/\r/\\r/g;
1082             s/\n/\\n/g;
1083             s/\t/\\t/g;
1084             s/([^\x20-\x7E])/sprintf('\\x%.2X', ord($1))/ge;
1085             $_;
1086             };
1087              
1088             my $Token = qr/[\x21\x23-\x27\x2A\x2B\x2D\x2E\x30-\x39\x41-\x5A\x5E-\x7A\x7C\x7E]/;
1089             my $Field_Content = qr/[[:print:]]+ (?: [\x20\x09]+ [[:print:]]+ )*/x;
1090              
1091             sub new {
1092 170     170   1081537 my ($class, %args) = @_;
1093 170         611 return bless {
1094             rbuf => '',
1095             timeout => 60,
1096             max_line_size => 16384,
1097             max_header_lines => 64,
1098             verify_SSL => HTTP::Tiny::_verify_SSL_default(),
1099             SSL_options => {},
1100             %args
1101             }, $class;
1102             }
1103              
1104             sub timeout {
1105 2     2   3 my ($self, $timeout) = @_;
1106 2 50       4 if ( @_ > 1 ) {
1107 2         3 $self->{timeout} = $timeout;
1108 2 50 33     45 if ( $self->{fh} && $self->{fh}->can('timeout') ) {
1109 0         0 $self->{fh}->timeout($timeout);
1110             }
1111             }
1112 2         4 return $self->{timeout};
1113             }
1114              
1115             sub connect {
1116 32 50   32   119 @_ == 5 || die(q/Usage: $handle->connect(scheme, host, port, peer)/ . "\n");
1117 32         109 my ($self, $scheme, $host, $port, $peer) = @_;
1118              
1119 32 100       104 if ( $scheme eq 'https' ) {
1120 29         126 $self->_assert_ssl;
1121             }
1122              
1123             $self->{fh} = $SOCKET_CLASS->new(
1124             PeerHost => $peer,
1125             PeerPort => $port,
1126             $self->{local_address} ?
1127             ( LocalAddr => $self->{local_address} ) : (),
1128             Proto => 'tcp',
1129             Type => SOCK_STREAM,
1130             Timeout => $self->{timeout},
1131 32 100       514 ) or die(qq/Could not connect to '$host:$port': $@\n/);
    100          
1132              
1133 31         2627716 $self->{fh}->setsockopt(IPPROTO_TCP, TCP_NODELAY, 1);
1134              
1135             binmode($self->{fh})
1136 31 50       3343 or die(qq/Could not binmode() socket: '$!'\n/);
1137              
1138 31 50       157 if ( $self->{keep_alive} ) {
1139 31 50       152 unless ( defined( $self->{fh}->setsockopt( SOL_SOCKET, SO_KEEPALIVE, 1 ) ) ) {
1140 0         0 CORE::close($self->{fh});
1141 0         0 die(qq/Could not set SO_KEEPALIVE on socket: '$!'\n/);
1142             }
1143             }
1144              
1145 31 100       661 $self->start_ssl($host) if $scheme eq 'https';
1146              
1147 18         181 $self->{scheme} = $scheme;
1148 18         80 $self->{host} = $host;
1149 18         64 $self->{peer} = $peer;
1150 18         75 $self->{port} = $port;
1151 18         171 $self->{pid} = $$;
1152 18         91 $self->{tid} = _get_tid();
1153              
1154 18         171 return $self;
1155             }
1156              
1157             sub connected {
1158 18     18   51 my ($self) = @_;
1159 18 50 33     198 if ( $self->{fh} && $self->{fh}->connected ) {
1160             return wantarray
1161             ? ( $self->{fh}->peerhost, $self->{fh}->peerport )
1162 18 50       1224 : join( ':', $self->{fh}->peerhost, $self->{fh}->peerport );
1163             }
1164 0         0 return;
1165             }
1166              
1167             sub start_ssl {
1168 29     29   113 my ($self, $host) = @_;
1169              
1170             # As this might be used via CONNECT after an SSL session
1171             # to a proxy, we shut down any existing SSL before attempting
1172             # the handshake
1173 29 50       148 if ( ref($self->{fh}) eq 'IO::Socket::SSL' ) {
1174 0 0       0 unless ( $self->{fh}->stop_SSL ) {
1175 0         0 my $ssl_err = IO::Socket::SSL->errstr;
1176 0         0 die(qq/Error halting prior SSL connection: $ssl_err/);
1177             }
1178             }
1179              
1180 29         150 my $ssl_args = $self->_ssl_args($host);
1181             IO::Socket::SSL->start_SSL(
1182             $self->{fh},
1183             %$ssl_args,
1184             SSL_create_ctx_callback => sub {
1185 29     29   2572107 my $ctx = shift;
1186 29         1909 Net::SSLeay::CTX_set_mode($ctx, Net::SSLeay::MODE_AUTO_RETRY());
1187             },
1188 29         929 );
1189              
1190 29 100       3768942 unless ( ref($self->{fh}) eq 'IO::Socket::SSL' ) {
1191 13         87 my $ssl_err = IO::Socket::SSL->errstr;
1192 13         3157 die(qq/SSL connection failed for $host: $ssl_err\n/);
1193             }
1194             }
1195              
1196             sub close {
1197 2 50   2   8 @_ == 1 || die(q/Usage: $handle->close()/ . "\n");
1198 2         6 my ($self) = @_;
1199             CORE::close($self->{fh})
1200 2 50       17 or die(qq/Could not close socket: '$!'\n/);
1201             }
1202              
1203             sub write {
1204 361 50   361   805 @_ == 2 || die(q/Usage: $handle->write(buf)/ . "\n");
1205 361         673 my ($self, $buf) = @_;
1206              
1207 361 50       1555 if ( "$]" >= 5.008 ) {
1208 361 50       1045 utf8::downgrade($buf, 1)
1209             or die(qq/Wide character in write()\n/);
1210             }
1211              
1212 361         522 my $len = length $buf;
1213 361         475 my $off = 0;
1214              
1215 361         3973 local $SIG{PIPE} = 'IGNORE';
1216              
1217 361         547 while () {
1218 361 50       984 $self->can_write
1219             or die(qq/Timed out while waiting for socket to become ready for writing\n/);
1220 361         10768 my $r = syswrite($self->{fh}, $buf, $len, $off);
1221 361 50       6552 if (defined $r) {
    0          
    0          
1222 361         551 $len -= $r;
1223 361         547 $off += $r;
1224 361 50       992 last unless $len > 0;
1225             }
1226             elsif ($! == EPIPE) {
1227 0         0 die(qq/Socket closed by remote server: $!\n/);
1228             }
1229             elsif ($! != EINTR) {
1230 0 0       0 if ($self->{fh}->can('errstr')){
1231 0         0 my $err = $self->{fh}->errstr();
1232 0         0 die (qq/Could not write to SSL socket: '$err'\n /);
1233             }
1234             else {
1235 0         0 die(qq/Could not write to socket: '$!'\n/);
1236             }
1237              
1238             }
1239             }
1240 361         3411 return $off;
1241             }
1242              
1243             sub read {
1244 315 50 66 315   1170 @_ == 2 || @_ == 3 || die(q/Usage: $handle->read(len [, allow_partial])/ . "\n");
1245 315         629 my ($self, $len, $allow_partial) = @_;
1246              
1247 315         506 my $buf = '';
1248 315         615 my $got = length $self->{rbuf};
1249              
1250 315 100       735 if ($got) {
1251 266 100       551 my $take = ($got < $len) ? $got : $len;
1252 266         839 $buf = substr($self->{rbuf}, 0, $take, '');
1253 266         446 $len -= $take;
1254             }
1255              
1256             # Ignore SIGPIPE because SSL reads can result in writes that might error.
1257             # See "Expecting exactly the same behavior as plain sockets" in
1258             # https://metacpan.org/dist/IO-Socket-SSL/view/lib/IO/Socket/SSL.pod#Common-Usage-Errors
1259 315         3635 local $SIG{PIPE} = 'IGNORE';
1260              
1261 315         817 while ($len > 0) {
1262 880 50       2645 $self->can_read
1263             or die(q/Timed out while waiting for socket to become ready for reading/ . "\n");
1264 880         4746 my $r = sysread($self->{fh}, $buf, $len, length $buf);
1265 880 50       79334 if (defined $r) {
    0          
1266 880 100       2457 last unless $r;
1267 876         2723 $len -= $r;
1268             }
1269             elsif ($! != EINTR) {
1270 0 0       0 if ($self->{fh}->can('errstr')){
1271 0         0 my $err = $self->{fh}->errstr();
1272 0         0 die (qq/Could not read from SSL socket: '$err'\n /);
1273             }
1274             else {
1275 0         0 die(qq/Could not read from socket: '$!'\n/);
1276             }
1277             }
1278             }
1279 315 50 66     965 if ($len && !$allow_partial) {
1280 0         0 die(qq/Unexpected end of stream\n/);
1281             }
1282 315         3405 return $buf;
1283             }
1284              
1285             sub readline {
1286 1071 50   1071   2199 @_ == 1 || die(q/Usage: $handle->readline()/ . "\n");
1287 1071         1735 my ($self) = @_;
1288              
1289 1071         1377 while () {
1290 1270 100       7418 if ($self->{rbuf} =~ s/\A ([^\x0D\x0A]* \x0D?\x0A)//x) {
1291 1071         3617 return $1;
1292             }
1293 199 50       813 if (length $self->{rbuf} >= $self->{max_line_size}) {
1294 0         0 die(qq/Line size exceeds the maximum allowed size of $self->{max_line_size}\n/);
1295             }
1296             $self->can_read
1297 199 50       625 or die(qq/Timed out while waiting for socket to become ready for reading\n/);
1298 199         5711 my $r = sysread($self->{fh}, $self->{rbuf}, BUFSIZE, length $self->{rbuf});
1299 199 50       34338 if (defined $r) {
    0          
1300 199 50       606 last unless $r;
1301             }
1302             elsif ($! != EINTR) {
1303 0 0       0 if ($self->{fh}->can('errstr')){
1304 0         0 my $err = $self->{fh}->errstr();
1305 0         0 die (qq/Could not read from SSL socket: '$err'\n /);
1306             }
1307             else {
1308 0         0 die(qq/Could not read from socket: '$!'\n/);
1309             }
1310             }
1311             }
1312 0         0 die(qq/Unexpected end of stream while looking for line\n/);
1313             }
1314              
1315             sub read_header_lines {
1316 162 50 66 162   563 @_ == 1 || @_ == 2 || die(q/Usage: $handle->read_header_lines([headers])/ . "\n");
1317 162         363 my ($self, $headers) = @_;
1318 162   100     828 $headers ||= {};
1319 162         259 my $lines = 0;
1320 162         264 my $val;
1321              
1322 162         312 while () {
1323 812         1576 my $line = $self->readline;
1324              
1325 812 50       4160 if (++$lines >= $self->{max_header_lines}) {
    100          
    100          
    50          
1326 0         0 die(qq/Header lines exceeds maximum number allowed of $self->{max_header_lines}\n/);
1327             }
1328             elsif ($line =~ /\A ([^\x00-\x1F\x7F:]+) : [\x09\x20]* ([^\x0D\x0A]*)/x) {
1329 647         1543 my ($field_name) = lc $1;
1330 647 100       1401 if (exists $headers->{$field_name}) {
1331 14         32 for ($headers->{$field_name}) {
1332 14 100       54 $_ = [$_] unless ref $_ eq "ARRAY";
1333 14         45 push @$_, $2;
1334 14         34 $val = \$_->[-1];
1335             }
1336             }
1337             else {
1338 633         2349 $val = \($headers->{$field_name} = $2);
1339             }
1340             }
1341             elsif ($line =~ /\A [\x09\x20]+ ([^\x0D\x0A]*)/x) {
1342 3 50       5 $val
1343             or die(qq/Unexpected header continuation line\n/);
1344 3 100       8 next unless length $1;
1345 2 100       5 $$val .= ' ' if length $$val;
1346 2         3 $$val .= $1;
1347             }
1348             elsif ($line =~ /\A \x0D?\x0A \z/x) {
1349 162         317 last;
1350             }
1351             else {
1352 0         0 die(q/Malformed header line: / . $Printable->($line) . "\n");
1353             }
1354             }
1355 162         1658 return $headers;
1356             }
1357              
1358             sub write_request {
1359 18 50   18   171 @_ == 2 || die(q/Usage: $handle->write_request(request)/ . "\n");
1360 18         68 my($self, $request) = @_;
1361 18         66 $self->write_request_header(@{$request}{qw/method uri headers header_case/});
  18         148  
1362 18 50       77 $self->write_body($request) if $request->{cb};
1363 18         37 return;
1364             }
1365              
1366             # Standard request header names/case from HTTP/1.1 RFCs
1367             my @rfc_request_headers = qw(
1368             Accept Accept-Charset Accept-Encoding Accept-Language Authorization
1369             Cache-Control Connection Content-Length Expect From Host
1370             If-Match If-Modified-Since If-None-Match If-Range If-Unmodified-Since
1371             Max-Forwards Pragma Proxy-Authorization Range Referer TE Trailer
1372             Transfer-Encoding Upgrade User-Agent Via
1373             );
1374              
1375             my @other_request_headers = qw(
1376             Content-Encoding Content-MD5 Content-Type Cookie DNT Date Origin
1377             X-XSS-Protection
1378             );
1379              
1380             my %HeaderCase = map { lc($_) => $_ } @rfc_request_headers, @other_request_headers;
1381              
1382             # to avoid multiple small writes and hence nagle, you can pass the method line or anything else to
1383             # combine writes.
1384             sub write_header_lines {
1385 146 50 33 146   1201 (@_ >= 2 && @_ <= 4 && ref $_[1] eq 'HASH') || die(q/Usage: $handle->write_header_lines(headers, [header_case, prefix])/ . "\n");
      33        
1386 146         356 my($self, $headers, $header_case, $prefix_data) = @_;
1387 146   100     600 $header_case ||= {};
1388              
1389 146 100       432 my $buf = (defined $prefix_data ? $prefix_data : '');
1390              
1391             # Per RFC, control fields should be listed first
1392 146         296 my %seen;
1393 146         357 for my $k ( qw/host cache-control expect max-forwards pragma range te/ ) {
1394 1022 100       2296 next unless exists $headers->{$k};
1395 142         340 $seen{$k}++;
1396 142         421 my $field_name = $HeaderCase{$k};
1397 142         325 my $v = $headers->{$k};
1398 142 50       481 for (ref $v eq 'ARRAY' ? @$v : $v) {
1399 142 50       335 $_ = '' unless defined $_;
1400 142         514 $buf .= "$field_name: $_\x0D\x0A";
1401             }
1402             }
1403              
1404             # Other headers sent in arbitrary order
1405 146         705 while (my ($k, $v) = each %$headers) {
1406 490         856 my $field_name = lc $k;
1407 490 100       1431 next if $seen{$field_name};
1408 349 100       762 if (exists $HeaderCase{$field_name}) {
1409 338         659 $field_name = $HeaderCase{$field_name};
1410             }
1411             else {
1412 11 100       29 if (exists $header_case->{$field_name}) {
1413 5         13 $field_name = $header_case->{$field_name};
1414             }
1415             else {
1416 6         59 $field_name =~ s/\b(\w)/\u$1/g;
1417             }
1418 11 100       304 $field_name =~ /\A $Token+ \z/xo
1419             or die(q/Invalid HTTP header field name: / . $Printable->($field_name) . "\n");
1420 10         36 $HeaderCase{lc $field_name} = $field_name;
1421             }
1422 348 100       759 for (ref $v eq 'ARRAY' ? @$v : $v) {
1423             # unwrap a field value if pre-wrapped by user
1424 351         705 s/\x0D?\x0A\s+/ /g;
1425 351 50 66     6170 die(qq/Invalid HTTP header field value ($field_name): / . $Printable->($_). "\n")
1426             unless $_ eq '' || /\A $Field_Content \z/xo;
1427 351 50       881 $_ = '' unless defined $_;
1428 351         1433 $buf .= "$field_name: $_\x0D\x0A";
1429             }
1430             }
1431 145         252 $buf .= "\x0D\x0A";
1432 145         493 return $self->write($buf);
1433             }
1434              
1435             # return value indicates whether message length was defined; this is generally
1436             # true unless there was no content-length header and we just read until EOF.
1437             # Other message length errors are thrown as exceptions
1438             sub read_body {
1439 137 50   137   397 @_ == 3 || die(q/Usage: $handle->read_body(callback, response)/ . "\n");
1440 137         324 my ($self, $cb, $response) = @_;
1441 137   100     540 my $te = $response->{headers}{'transfer-encoding'} || '';
1442 137 100       470 my $chunked = grep { /chunked/i } ( ref $te eq 'ARRAY' ? @$te : $te ) ;
  138         470  
1443 137 100       569 return $chunked
1444             ? $self->read_chunked_body($cb, $response)
1445             : $self->read_content_body($cb, $response);
1446             }
1447              
1448             sub write_body {
1449 30 50   30   67 @_ == 2 || die(q/Usage: $handle->write_body(request)/ . "\n");
1450 30         54 my ($self, $request) = @_;
1451 30 100       72 if (exists $request->{headers}{'content-length'}) {
1452 27 100       55 return unless $request->{headers}{'content-length'};
1453 26         62 return $self->write_content_body($request);
1454             }
1455             else {
1456 3         14 return $self->write_chunked_body($request);
1457             }
1458             }
1459              
1460             sub read_content_body {
1461 226 50 66 226   3223 @_ == 3 || @_ == 4 || die(q/Usage: $handle->read_content_body(callback, response, [read_length])/ . "\n");
1462 226         566 my ($self, $cb, $response, $content_length) = @_;
1463 226   100     794 $content_length ||= $response->{headers}{'content-length'};
1464              
1465 226 100       506 if ( defined $content_length ) {
1466 224         464 my $len = $content_length;
1467 224         675 while ($len > 0) {
1468 213 100       506 my $read = ($len > BUFSIZE) ? BUFSIZE : $len;
1469 213         596 $cb->($self->read($read, 0), $response);
1470 212         761 $len -= $read;
1471             }
1472 223         1233 return length($self->{rbuf}) == 0;
1473             }
1474              
1475 2         5 my $chunk;
1476 2         9 $cb->($chunk, $response) while length( $chunk = $self->read(BUFSIZE, 1) );
1477              
1478 2         12 return;
1479             }
1480              
1481             sub write_content_body {
1482 27 50   27   62 @_ == 2 || die(q/Usage: $handle->write_content_body(request)/ . "\n");
1483 27         43 my ($self, $request) = @_;
1484              
1485 27         54 my ($len, $content_length) = (0, $request->{headers}{'content-length'});
1486 27         32 while () {
1487 181         466 my $data = $request->{cb}->();
1488              
1489 181 100 100     818 defined $data && length $data
1490             or last;
1491              
1492 154 50       582 if ( "$]" >= 5.008 ) {
1493 154 50       350 utf8::downgrade($data, 1)
1494             or die(qq/Wide character in write_content()\n/);
1495             }
1496              
1497 154         271 $len += $self->write($data);
1498             }
1499              
1500 27 50       59 $len == $content_length
1501             or die(qq/Content-Length mismatch (got: $len expected: $content_length)\n/);
1502              
1503 27         53 return $len;
1504             }
1505              
1506             sub read_chunked_body {
1507 12 50   12   127 @_ == 3 || die(q/Usage: $handle->read_chunked_body(callback, $response)/ . "\n");
1508 12         35 my ($self, $cb, $response) = @_;
1509              
1510 12         22 while () {
1511 110         367 my $head = $self->readline;
1512              
1513 110 50       507 $head =~ /\A ([A-Fa-f0-9]+)/x
1514             or die(q/Malformed chunk head: / . $Printable->($head) . "\n");
1515              
1516 110 100       338 my $len = hex($1)
1517             or last;
1518              
1519 98         393 $self->read_content_body($cb, $response, $len);
1520              
1521 98 50       265 $self->read(2) eq "\x0D\x0A"
1522             or die(qq/Malformed chunk: missing CRLF after chunk data\n/);
1523             }
1524 12         55 $self->read_header_lines($response->{headers});
1525 12         90 return 1;
1526             }
1527              
1528             sub write_chunked_body {
1529 5 50   5   127 @_ == 2 || die(q/Usage: $handle->write_chunked_body(request)/ . "\n");
1530 5         14 my ($self, $request) = @_;
1531              
1532 5         11 my $len = 0;
1533 5         8 while () {
1534 59         232 my $data = $request->{cb}->();
1535              
1536 59 100 100     269 defined $data && length $data
1537             or last;
1538              
1539 54 50       174 if ( "$]" >= 5.008 ) {
1540 54 50       112 utf8::downgrade($data, 1)
1541             or die(qq/Wide character in write_chunked_body()\n/);
1542             }
1543              
1544 54         61 $len += length $data;
1545              
1546 54         112 my $chunk = sprintf '%X', length $data;
1547 54         67 $chunk .= "\x0D\x0A";
1548 54         61 $chunk .= $data;
1549 54         58 $chunk .= "\x0D\x0A";
1550              
1551 54         88 $self->write($chunk);
1552             }
1553 5         18 $self->write("0\x0D\x0A");
1554 5 100       20 if ( ref $request->{trailer_cb} eq 'CODE' ) {
1555 2         28 $self->write_header_lines($request->{trailer_cb}->())
1556             }
1557             else {
1558 3         10 $self->write("\x0D\x0A");
1559             }
1560 5         33 return $len;
1561             }
1562              
1563             sub read_response_header {
1564 149 50   149   444 @_ == 1 || die(q/Usage: $handle->read_response_header()/ . "\n");
1565 149         301 my ($self) = @_;
1566              
1567 149         450 my $line = $self->readline;
1568              
1569 149 100       1193 $line =~ /\A (HTTP\/(0*\d+\.0*\d+)) [\x09\x20]+ ([0-9]{3}) (?: [\x09\x20]+ ([^\x0D\x0A]*) )? \x0D?\x0A/x
1570             or die(q/Malformed Status-Line: / . $Printable->($line). "\n");
1571              
1572 147         974 my ($protocol, $version, $status, $reason) = ($1, $2, $3, $4);
1573 147 100       326 $reason = "" unless defined $reason;
1574              
1575 147 100       836 die (qq/Unsupported HTTP protocol: $protocol\n/)
1576             unless $version =~ /0*1\.0*[01]/;
1577              
1578             return {
1579 145         546 status => $status,
1580             reason => $reason,
1581             headers => $self->read_header_lines,
1582             protocol => $protocol,
1583             };
1584             }
1585              
1586             sub write_request_header {
1587 142 50   142   455 @_ == 5 || die(q/Usage: $handle->write_request_header(method, request_uri, headers, header_case)/ . "\n");
1588 142         395 my ($self, $method, $request_uri, $headers, $header_case) = @_;
1589              
1590 142         641 return $self->write_header_lines($headers, $header_case, "$method $request_uri HTTP/1.1\x0D\x0A");
1591             }
1592              
1593             sub _do_timeout {
1594 904     904   2227 my ($self, $type, $timeout) = @_;
1595             $timeout = $self->{timeout}
1596 904 50 33     2951 unless defined $timeout && $timeout >= 0;
1597              
1598 904         3204 my $fd = fileno $self->{fh};
1599 904 50 33     14415 defined $fd && $fd >= 0
1600             or die(qq/select(2): 'Bad file descriptor'\n/);
1601              
1602 904         1673 my $initial = time;
1603 904         1486 my $pending = $timeout;
1604 904         1434 my $nfound;
1605              
1606 904         4322 vec(my $fdset = '', $fd, 1) = 1;
1607              
1608 904         1941 while () {
1609 904 100       1211018 $nfound = ($type eq 'read')
1610             ? select($fdset, undef, undef, $pending)
1611             : select(undef, $fdset, undef, $pending) ;
1612 904 50       2971 if ($nfound == -1) {
1613 0 0       0 $! == EINTR
1614             or die(qq/select(2): '$!'\n/);
1615 0 0 0     0 redo if !$timeout || ($pending = $timeout - (time - $initial)) > 0;
1616 0         0 $nfound = 0;
1617             }
1618 904         1564 last;
1619             }
1620 904         2268 $! = 0;
1621 904         2907 return $nfound;
1622             }
1623              
1624             sub can_read {
1625 935 50 33 935   2579 @_ == 1 || @_ == 2 || die(q/Usage: $handle->can_read([timeout])/ . "\n");
1626 935         1897 my $self = shift;
1627 935 100       2897 if ( ref($self->{fh}) eq 'IO::Socket::SSL' ) {
1628 924 100       3179 return 1 if $self->{fh}->pending;
1629             }
1630 886         16004 return $self->_do_timeout('read', @_)
1631             }
1632              
1633             sub can_write {
1634 18 50 33 18   80 @_ == 1 || @_ == 2 || die(q/Usage: $handle->can_write([timeout])/ . "\n");
1635 18         41 my $self = shift;
1636 18         74 return $self->_do_timeout('write', @_)
1637             }
1638              
1639             sub _has_keep_alive_expired {
1640 13     13   24 my $self = shift;
1641 13 50       49 return unless $self->{keep_alive_timeout} > 0;
1642 0         0 my $now = Time::HiRes::time();
1643 0   0     0 return $now - ($self->{last_used} || $now) > $self->{keep_alive_timeout};
1644             }
1645              
1646             sub _update_last_used {
1647 43     43   73 my $self = shift;
1648 43 50       165 return unless $self->{keep_alive_timeout} > 0;
1649 0         0 $self->{last_used} = Time::HiRes::time();
1650             }
1651              
1652             sub _assert_ssl {
1653 29     29   143 my($ok, $reason) = HTTP::Tiny->can_ssl();
1654 29 50       122 die $reason unless $ok;
1655             }
1656              
1657             sub can_reuse {
1658 16     16   33 my ($self,$scheme,$host,$port,$peer) = @_;
1659             return 0 if
1660             $self->{pid} != $$
1661             || $self->{tid} != _get_tid()
1662             || length($self->{rbuf})
1663             || $scheme ne $self->{scheme}
1664             || $host ne $self->{host}
1665             || $port ne $self->{port}
1666             || $peer ne $self->{peer}
1667             || $self->_has_keep_alive_expired()
1668 16 100 33     115 || eval { $self->can_read(0) }
  13   33     37  
      66        
      100        
      100        
      66        
      66        
      66        
      66        
1669             || $@ ;
1670 5         54 return 1;
1671             }
1672              
1673             sub _find_CA {
1674 27     27   72 my $self = shift;
1675              
1676 27         97 my $ca_file = $self->{SSL_options}->{SSL_ca_file};
1677              
1678 27 100       110 if ( defined $ca_file ) {
1679 4 100       245 unless ( -r $ca_file ) {
1680 1         9 die qq/SSL_ca_file '$ca_file' not found or not readable\n/;
1681             }
1682 3         36 return ( SSL_ca_file => $ca_file );
1683             }
1684              
1685             # Return default_ca() parameters from IO::Socket::SSL. It looks for the
1686             # default bundle and directory from Net::SSLeay, handles $ENV{SSL_CERT_FILE}
1687             # and $ENV{SSL_CERT_DIR}, and finally fails over to Mozilla::CA
1688             #
1689 23         167 my %default_ca = IO::Socket::SSL::default_ca();
1690 23 50       2988 return %default_ca if %default_ca;
1691              
1692             # If IO::Socket::SSL::default_ca() was unable to find a CA bundle, look for
1693             # one in well known locations as a last resort. Cert list copied from golang
1694             # src/crypto/x509/root_unix.go
1695             #
1696 0         0 foreach my $ca_bundle (
1697             "/etc/ssl/certs/ca-certificates.crt", # Debian/Ubuntu/Gentoo etc.
1698             "/etc/pki/tls/certs/ca-bundle.crt", # Fedora/RHEL
1699             "/etc/ssl/ca-bundle.pem", # OpenSUSE
1700             "/etc/openssl/certs/ca-certificates.crt", # NetBSD
1701             "/etc/ssl/cert.pem", # OpenBSD
1702             "/usr/local/share/certs/ca-root-nss.crt", # FreeBSD/DragonFly
1703             "/etc/pki/tls/cacert.pem", # OpenELEC
1704             "/etc/certs/ca-certificates.crt", # Solaris 11.2+
1705             ) {
1706 0 0       0 return ( SSL_ca_file => $ca_bundle ) if -e $ca_bundle;
1707             }
1708              
1709 0         0 die qq/Couldn't find a CA bundle with which to verify the SSL certificate.\n/
1710             . qq/Try installing one from your OS vendor, or Mozilla::CA from CPAN\n/;
1711             }
1712              
1713             # not for internal use; backcompat shim only
1714             sub _find_CA_file {
1715 1     1   1245 my $self = shift;
1716 1         5 my %res = $self->_find_CA();
1717 1         7 return $res{SSL_ca_file};
1718             }
1719              
1720             # for thread safety, we need to know thread id if threads are loaded
1721             sub _get_tid {
1722 31     31   345 no warnings 'reserved'; # for 'threads'
  31         80  
  31         13397  
1723 154 50   154   4222 return threads->can("tid") ? threads->tid : 0;
1724             }
1725              
1726             sub _ssl_args {
1727 29     29   83 my ($self, $host) = @_;
1728              
1729 29         61 my %ssl_args;
1730              
1731             # This test reimplements IO::Socket::SSL::can_client_sni(), which wasn't
1732             # added until IO::Socket::SSL 1.84
1733 29 50       4138 if ( Net::SSLeay::OPENSSL_VERSION_NUMBER() >= 0x01000000 ) {
1734 29         284 $ssl_args{SSL_hostname} = $host, # Sane SNI support
1735             }
1736              
1737 29 100       184 if ($self->{verify_SSL}) {
1738 22         74 $ssl_args{SSL_verifycn_scheme} = 'http'; # enable CN validation
1739 22         62 $ssl_args{SSL_verifycn_name} = $host; # set validation hostname
1740 22         69 $ssl_args{SSL_verify_mode} = 0x01; # enable cert validation
1741              
1742 22         147 %ssl_args = ( %ssl_args, $self->_find_CA );
1743             }
1744             else {
1745 7         27 $ssl_args{SSL_verifycn_scheme} = 'none'; # disable CN validation
1746 7         31 $ssl_args{SSL_verify_mode} = 0x00; # disable cert validation
1747             }
1748              
1749             # user options override settings from verify_SSL
1750 29         74 for my $k ( keys %{$self->{SSL_options}} ) {
  29         178  
1751 9 50       60 $ssl_args{$k} = $self->{SSL_options}{$k} if $k =~ m/^SSL_/;
1752             }
1753              
1754 29         100 return \%ssl_args;
1755             }
1756              
1757             1;
1758              
1759             __END__