1# vim: ts=4 sts=4 sw=4 et:
2package HTTP::Tiny;
3use strict;
4use warnings;
5# ABSTRACT: A small, simple, correct HTTP/1.1 client
6our $VERSION = '0.043'; # VERSION
7
8use Carp ();
9
10# =method new
11#
12#     $http = HTTP::Tiny->new( %attributes );
13#
14# This constructor returns a new HTTP::Tiny object.  Valid attributes include:
15#
16# =for :list
17# * C<agent>
18# A user-agent string (defaults to 'HTTP-Tiny/$VERSION'). If C<agent> ends in a space character, the default user-agent string is appended.
19# * C<cookie_jar>
20# An instance of L<HTTP::CookieJar> or equivalent class that supports the C<add> and C<cookie_header> methods
21# * C<default_headers>
22# A hashref of default headers to apply to requests
23# * C<local_address>
24# The local IP address to bind to
25# * C<keep_alive>
26# Whether to reuse the last connection (if for the same scheme, host and port) (defaults to 1)
27# * C<max_redirect>
28# Maximum number of redirects allowed (defaults to 5)
29# * C<max_size>
30# Maximum response size (only when not using a data callback).  If defined, responses larger than this will return an exception.
31# * C<http_proxy>
32# URL of a proxy server to use for HTTP connections (default is C<$ENV{http_proxy}> if set)
33# * C<https_proxy>
34# URL of a proxy server to use for HTTPS connections (default is C<$ENV{https_proxy}> if set)
35# * C<proxy>
36# URL of a generic proxy server for both HTTP and HTTPS connections (default is C<$ENV{all_proxy}> if set)
37# * C<no_proxy>
38# List of domain suffixes that should not be proxied.  Must be a comma-separated string or an array reference. (default is C<$ENV{no_proxy}>)
39# * C<timeout>
40# Request timeout in seconds (default is 60)
41# * C<verify_SSL>
42# A boolean that indicates whether to validate the SSL certificate of an C<https>
43# connection (default is false)
44# * C<SSL_options>
45# A hashref of C<SSL_*> options to pass through to L<IO::Socket::SSL>
46#
47# Exceptions from C<max_size>, C<timeout> or other errors will result in a
48# pseudo-HTTP status code of 599 and a reason of "Internal Exception". The
49# content field in the response will contain the text of the exception.
50#
51# The C<keep_alive> parameter enables a persistent connection, but only to a
52# single destination scheme, host and port.  Also, if any connection-relevant
53# attributes are modified, a persistent connection will be dropped.  If you want
54# persistent connections across multiple destinations, use multiple HTTP::Tiny
55# objects.
56#
57# See L</SSL SUPPORT> for more on the C<verify_SSL> and C<SSL_options> attributes.
58#
59# =cut
60
61my @attributes;
62BEGIN {
63    @attributes = qw(
64        cookie_jar default_headers http_proxy https_proxy keep_alive
65        local_address max_redirect max_size proxy no_proxy timeout
66        SSL_options verify_SSL
67    );
68    my %persist_ok = map {; $_ => 1 } qw(
69        cookie_jar default_headers max_redirect max_size
70    );
71    no strict 'refs';
72    no warnings 'uninitialized';
73    for my $accessor ( @attributes ) {
74        *{$accessor} = sub {
75            @_ > 1
76                ? do {
77                    delete $_[0]->{handle} if !$persist_ok{$accessor} && $_[1] ne $_[0]->{$accessor};
78                    $_[0]->{$accessor} = $_[1]
79                }
80                : $_[0]->{$accessor};
81        };
82    }
83}
84
85sub agent {
86    my($self, $agent) = @_;
87    if( @_ > 1 ){
88        $self->{agent} =
89            (defined $agent && $agent =~ / $/) ? $agent . $self->_agent : $agent;
90    }
91    return $self->{agent};
92}
93
94sub new {
95    my($class, %args) = @_;
96
97    my $self = {
98        max_redirect => 5,
99        timeout      => 60,
100        keep_alive   => 1,
101        verify_SSL   => $args{verify_SSL} || $args{verify_ssl} || 0, # no verification by default
102        no_proxy     => $ENV{no_proxy},
103    };
104
105    bless $self, $class;
106
107    $class->_validate_cookie_jar( $args{cookie_jar} ) if $args{cookie_jar};
108
109    for my $key ( @attributes ) {
110        $self->{$key} = $args{$key} if exists $args{$key}
111    }
112
113    $self->agent( exists $args{agent} ? $args{agent} : $class->_agent );
114
115    $self->_set_proxies;
116
117    return $self;
118}
119
120sub _set_proxies {
121    my ($self) = @_;
122
123    if (! $self->{proxy} ) {
124        $self->{proxy} = $ENV{all_proxy} || $ENV{ALL_PROXY};
125        if ( defined $self->{proxy} ) {
126            $self->_split_proxy( 'generic proxy' => $self->{proxy} ); # validate
127        }
128        else {
129            delete $self->{proxy};
130        }
131    }
132
133    if (! $self->{http_proxy} ) {
134        $self->{http_proxy} = $ENV{http_proxy} || $self->{proxy};
135        if ( defined $self->{http_proxy} ) {
136            $self->_split_proxy( http_proxy => $self->{http_proxy} ); # validate
137            $self->{_has_proxy}{http} = 1;
138        }
139        else {
140            delete $self->{http_proxy};
141        }
142    }
143
144    if (! $self->{https_proxy} ) {
145        $self->{https_proxy} = $ENV{https_proxy} || $ENV{HTTPS_PROXY} || $self->{proxy};
146        if ( $self->{https_proxy} ) {
147            $self->_split_proxy( https_proxy => $self->{https_proxy} ); # validate
148            $self->{_has_proxy}{https} = 1;
149        }
150        else {
151            delete $self->{https_proxy};
152        }
153    }
154
155    # Split no_proxy to array reference if not provided as such
156    unless ( ref $self->{no_proxy} eq 'ARRAY' ) {
157        $self->{no_proxy} =
158            (defined $self->{no_proxy}) ? [ split /\s*,\s*/, $self->{no_proxy} ] : [];
159    }
160
161    return;
162}
163
164# =method get|head|put|post|delete
165#
166#     $response = $http->get($url);
167#     $response = $http->get($url, \%options);
168#     $response = $http->head($url);
169#
170# These methods are shorthand for calling C<request()> for the given method.  The
171# URL must have unsafe characters escaped and international domain names encoded.
172# See C<request()> for valid options and a description of the response.
173#
174# The C<success> field of the response will be true if the status code is 2XX.
175#
176# =cut
177
178for my $sub_name ( qw/get head put post delete/ ) {
179    my $req_method = uc $sub_name;
180    no strict 'refs';
181    eval <<"HERE"; ## no critic
182    sub $sub_name {
183        my (\$self, \$url, \$args) = \@_;
184        \@_ == 2 || (\@_ == 3 && ref \$args eq 'HASH')
185        or Carp::croak(q/Usage: \$http->$sub_name(URL, [HASHREF])/ . "\n");
186        return \$self->request('$req_method', \$url, \$args || {});
187    }
188HERE
189}
190
191# =method post_form
192#
193#     $response = $http->post_form($url, $form_data);
194#     $response = $http->post_form($url, $form_data, \%options);
195#
196# This method executes a C<POST> request and sends the key/value pairs from a
197# form data hash or array reference to the given URL with a C<content-type> of
198# C<application/x-www-form-urlencoded>.  If data is provided as an array
199# reference, the order is preserved; if provided as a hash reference, the terms
200# are sorted on key and value for consistency.  See documentation for the
201# C<www_form_urlencode> method for details on the encoding.
202#
203# The URL must have unsafe characters escaped and international domain names
204# encoded.  See C<request()> for valid options and a description of the response.
205# Any C<content-type> header or content in the options hashref will be ignored.
206#
207# The C<success> field of the response will be true if the status code is 2XX.
208#
209# =cut
210
211sub post_form {
212    my ($self, $url, $data, $args) = @_;
213    (@_ == 3 || @_ == 4 && ref $args eq 'HASH')
214        or Carp::croak(q/Usage: $http->post_form(URL, DATAREF, [HASHREF])/ . "\n");
215
216    my $headers = {};
217    while ( my ($key, $value) = each %{$args->{headers} || {}} ) {
218        $headers->{lc $key} = $value;
219    }
220    delete $args->{headers};
221
222    return $self->request('POST', $url, {
223            %$args,
224            content => $self->www_form_urlencode($data),
225            headers => {
226                %$headers,
227                'content-type' => 'application/x-www-form-urlencoded'
228            },
229        }
230    );
231}
232
233# =method mirror
234#
235#     $response = $http->mirror($url, $file, \%options)
236#     if ( $response->{success} ) {
237#         print "$file is up to date\n";
238#     }
239#
240# Executes a C<GET> request for the URL and saves the response body to the file
241# name provided.  The URL must have unsafe characters escaped and international
242# domain names encoded.  If the file already exists, the request will include an
243# C<If-Modified-Since> header with the modification timestamp of the file.  You
244# may specify a different C<If-Modified-Since> header yourself in the C<<
245# $options->{headers} >> hash.
246#
247# The C<success> field of the response will be true if the status code is 2XX
248# or if the status code is 304 (unmodified).
249#
250# If the file was modified and the server response includes a properly
251# formatted C<Last-Modified> header, the file modification time will
252# be updated accordingly.
253#
254# =cut
255
256sub mirror {
257    my ($self, $url, $file, $args) = @_;
258    @_ == 3 || (@_ == 4 && ref $args eq 'HASH')
259      or Carp::croak(q/Usage: $http->mirror(URL, FILE, [HASHREF])/ . "\n");
260    if ( -e $file and my $mtime = (stat($file))[9] ) {
261        $args->{headers}{'if-modified-since'} ||= $self->_http_date($mtime);
262    }
263    my $tempfile = $file . int(rand(2**31));
264
265    require Fcntl;
266    sysopen my $fh, $tempfile, Fcntl::O_CREAT()|Fcntl::O_EXCL()|Fcntl::O_WRONLY()
267       or Carp::croak(qq/Error: Could not create temporary file $tempfile for downloading: $!\n/);
268    binmode $fh;
269    $args->{data_callback} = sub { print {$fh} $_[0] };
270    my $response = $self->request('GET', $url, $args);
271    close $fh
272        or Carp::croak(qq/Error: Caught error closing temporary file $tempfile: $!\n/);
273
274    if ( $response->{success} ) {
275        rename $tempfile, $file
276            or Carp::croak(qq/Error replacing $file with $tempfile: $!\n/);
277        my $lm = $response->{headers}{'last-modified'};
278        if ( $lm and my $mtime = $self->_parse_http_date($lm) ) {
279            utime $mtime, $mtime, $file;
280        }
281    }
282    $response->{success} ||= $response->{status} eq '304';
283    unlink $tempfile;
284    return $response;
285}
286
287# =method request
288#
289#     $response = $http->request($method, $url);
290#     $response = $http->request($method, $url, \%options);
291#
292# Executes an HTTP request of the given method type ('GET', 'HEAD', 'POST',
293# 'PUT', etc.) on the given URL.  The URL must have unsafe characters escaped and
294# international domain names encoded.
295#
296# If the URL includes a "user:password" stanza, they will be used for Basic-style
297# authorization headers.  (Authorization headers will not be included in a
298# redirected request.) For example:
299#
300#     $http->request('GET', 'http://Aladdin:open sesame@example.com/');
301#
302# If the "user:password" stanza contains reserved characters, they must
303# be percent-escaped:
304#
305#     $http->request('GET', 'http://john%40example.com:password@example.com/');
306#
307# A hashref of options may be appended to modify the request.
308#
309# Valid options are:
310#
311# =for :list
312# * C<headers>
313# A hashref containing headers to include with the request.  If the value for
314# a header is an array reference, the header will be output multiple times with
315# each value in the array.  These headers over-write any default headers.
316# * C<content>
317# A scalar to include as the body of the request OR a code reference
318# that will be called iteratively to produce the body of the request
319# * C<trailer_callback>
320# A code reference that will be called if it exists to provide a hashref
321# of trailing headers (only used with chunked transfer-encoding)
322# * C<data_callback>
323# A code reference that will be called for each chunks of the response
324# body received.
325#
326# If the C<content> option is a code reference, it will be called iteratively
327# to provide the content body of the request.  It should return the empty
328# string or undef when the iterator is exhausted.
329#
330# If the C<content> option is the empty string, no C<content-type> or
331# C<content-length> headers will be generated.
332#
333# If the C<data_callback> option is provided, it will be called iteratively until
334# the entire response body is received.  The first argument will be a string
335# containing a chunk of the response body, the second argument will be the
336# in-progress response hash reference, as described below.  (This allows
337# customizing the action of the callback based on the C<status> or C<headers>
338# received prior to the content body.)
339#
340# The C<request> method returns a hashref containing the response.  The hashref
341# will have the following keys:
342#
343# =for :list
344# * C<success>
345# Boolean indicating whether the operation returned a 2XX status code
346# * C<url>
347# URL that provided the response. This is the URL of the request unless
348# there were redirections, in which case it is the last URL queried
349# in a redirection chain
350# * C<status>
351# The HTTP status code of the response
352# * C<reason>
353# The response phrase returned by the server
354# * C<content>
355# The body of the response.  If the response does not have any content
356# or if a data callback is provided to consume the response body,
357# this will be the empty string
358# * C<headers>
359# A hashref of header fields.  All header field names will be normalized
360# to be lower case. If a header is repeated, the value will be an arrayref;
361# it will otherwise be a scalar string containing the value
362#
363# On an exception during the execution of the request, the C<status> field will
364# contain 599, and the C<content> field will contain the text of the exception.
365#
366# =cut
367
368my %idempotent = map { $_ => 1 } qw/GET HEAD PUT DELETE OPTIONS TRACE/;
369
370sub request {
371    my ($self, $method, $url, $args) = @_;
372    @_ == 3 || (@_ == 4 && ref $args eq 'HASH')
373      or Carp::croak(q/Usage: $http->request(METHOD, URL, [HASHREF])/ . "\n");
374    $args ||= {}; # we keep some state in this during _request
375
376    # RFC 2616 Section 8.1.4 mandates a single retry on broken socket
377    my $response;
378    for ( 0 .. 1 ) {
379        $response = eval { $self->_request($method, $url, $args) };
380        last unless $@ && $idempotent{$method}
381            && $@ =~ m{^(?:Socket closed|Unexpected end)};
382    }
383
384    if (my $e = $@) {
385        # maybe we got a response hash thrown from somewhere deep
386        if ( ref $e eq 'HASH' && exists $e->{status} ) {
387            return $e;
388        }
389
390        # otherwise, stringify it
391        $e = "$e";
392        $response = {
393            url     => $url,
394            success => q{},
395            status  => 599,
396            reason  => 'Internal Exception',
397            content => $e,
398            headers => {
399                'content-type'   => 'text/plain',
400                'content-length' => length $e,
401            }
402        };
403    }
404    return $response;
405}
406
407# =method www_form_urlencode
408#
409#     $params = $http->www_form_urlencode( $data );
410#     $response = $http->get("http://example.com/query?$params");
411#
412# This method converts the key/value pairs from a data hash or array reference
413# into a C<x-www-form-urlencoded> string.  The keys and values from the data
414# reference will be UTF-8 encoded and escaped per RFC 3986.  If a value is an
415# array reference, the key will be repeated with each of the values of the array
416# reference.  If data is provided as a hash reference, the key/value pairs in the
417# resulting string will be sorted by key and value for consistent ordering.
418#
419# =cut
420
421sub www_form_urlencode {
422    my ($self, $data) = @_;
423    (@_ == 2 && ref $data)
424        or Carp::croak(q/Usage: $http->www_form_urlencode(DATAREF)/ . "\n");
425    (ref $data eq 'HASH' || ref $data eq 'ARRAY')
426        or Carp::croak("form data must be a hash or array reference\n");
427
428    my @params = ref $data eq 'HASH' ? %$data : @$data;
429    @params % 2 == 0
430        or Carp::croak("form data reference must have an even number of terms\n");
431
432    my @terms;
433    while( @params ) {
434        my ($key, $value) = splice(@params, 0, 2);
435        if ( ref $value eq 'ARRAY' ) {
436            unshift @params, map { $key => $_ } @$value;
437        }
438        else {
439            push @terms, join("=", map { $self->_uri_escape($_) } $key, $value);
440        }
441    }
442
443    return join("&", (ref $data eq 'ARRAY') ? (@terms) : (sort @terms) );
444}
445
446#--------------------------------------------------------------------------#
447# private methods
448#--------------------------------------------------------------------------#
449
450my %DefaultPort = (
451    http => 80,
452    https => 443,
453);
454
455sub _agent {
456    my $class = ref($_[0]) || $_[0];
457    (my $default_agent = $class) =~ s{::}{-}g;
458    return $default_agent . "/" . ($class->VERSION || 0);
459}
460
461sub _request {
462    my ($self, $method, $url, $args) = @_;
463
464    my ($scheme, $host, $port, $path_query, $auth) = $self->_split_url($url);
465
466    my $request = {
467        method    => $method,
468        scheme    => $scheme,
469        host      => $host,
470        host_port => ($port == $DefaultPort{$scheme} ? $host : "$host:$port"),
471        uri       => $path_query,
472        headers   => {},
473    };
474
475    # We remove the cached handle so it is not reused in the case of redirect.
476    # If all is well, it will be recached at the end of _request.  We only
477    # reuse for the same scheme, host and port
478    my $handle = delete $self->{handle};
479    if ( $handle ) {
480        unless ( $handle->can_reuse( $scheme, $host, $port ) ) {
481            $handle->close;
482            undef $handle;
483        }
484    }
485    $handle ||= $self->_open_handle( $request, $scheme, $host, $port );
486
487    $self->_prepare_headers_and_cb($request, $args, $url, $auth);
488    $handle->write_request($request);
489
490    my $response;
491    do { $response = $handle->read_response_header }
492        until (substr($response->{status},0,1) ne '1');
493
494    $self->_update_cookie_jar( $url, $response ) if $self->{cookie_jar};
495
496    if ( my @redir_args = $self->_maybe_redirect($request, $response, $args) ) {
497        $handle->close;
498        return $self->_request(@redir_args, $args);
499    }
500
501    my $known_message_length;
502    if ($method eq 'HEAD' || $response->{status} =~ /^[23]04/) {
503        # response has no message body
504        $known_message_length = 1;
505    }
506    else {
507        my $data_cb = $self->_prepare_data_cb($response, $args);
508        $known_message_length = $handle->read_body($data_cb, $response);
509    }
510
511    if ( $self->{keep_alive}
512        && $known_message_length
513        && $response->{protocol} eq 'HTTP/1.1'
514        && ($response->{headers}{connection} || '') ne 'close'
515    ) {
516        $self->{handle} = $handle;
517    }
518    else {
519        $handle->close;
520    }
521
522    $response->{success} = substr( $response->{status}, 0, 1 ) eq '2';
523    $response->{url} = $url;
524    return $response;
525}
526
527sub _open_handle {
528    my ($self, $request, $scheme, $host, $port) = @_;
529
530    my $handle  = HTTP::Tiny::Handle->new(
531        timeout         => $self->{timeout},
532        SSL_options     => $self->{SSL_options},
533        verify_SSL      => $self->{verify_SSL},
534        local_address   => $self->{local_address},
535        keep_alive      => $self->{keep_alive}
536    );
537
538    if ($self->{_has_proxy}{$scheme} && ! grep { $host =~ /\Q$_\E$/ } @{$self->{no_proxy}}) {
539        return $self->_proxy_connect( $request, $handle );
540    }
541    else {
542        return $handle->connect($scheme, $host, $port);
543    }
544}
545
546sub _proxy_connect {
547    my ($self, $request, $handle) = @_;
548
549    my @proxy_vars;
550    if ( $request->{scheme} eq 'https' ) {
551        Carp::croak(qq{No https_proxy defined}) unless $self->{https_proxy};
552        @proxy_vars = $self->_split_proxy( https_proxy => $self->{https_proxy} );
553        if ( $proxy_vars[0] eq 'https' ) {
554            Carp::croak(qq{Can't proxy https over https: $request->{uri} via $self->{https_proxy}});
555        }
556    }
557    else {
558        Carp::croak(qq{No http_proxy defined}) unless $self->{http_proxy};
559        @proxy_vars = $self->_split_proxy( http_proxy => $self->{http_proxy} );
560    }
561
562    my ($p_scheme, $p_host, $p_port, $p_auth) = @proxy_vars;
563
564    if ( length $p_auth && ! defined $request->{headers}{'proxy-authorization'} ) {
565        $self->_add_basic_auth_header( $request, 'proxy-authorization' => $p_auth );
566    }
567
568    $handle->connect($p_scheme, $p_host, $p_port);
569
570    if ($request->{scheme} eq 'https') {
571        $self->_create_proxy_tunnel( $request, $handle );
572    }
573    else {
574        # non-tunneled proxy requires absolute URI
575        $request->{uri} = "$request->{scheme}://$request->{host_port}$request->{uri}";
576    }
577
578    return $handle;
579}
580
581sub _split_proxy {
582    my ($self, $type, $proxy) = @_;
583
584    my ($scheme, $host, $port, $path_query, $auth) = eval { $self->_split_url($proxy) };
585
586    unless(
587        defined($scheme) && length($scheme) && length($host) && length($port)
588        && $path_query eq '/'
589    ) {
590        Carp::croak(qq{$type URL must be in format http[s]://[auth@]<host>:<port>/\n});
591    }
592
593    return ($scheme, $host, $port, $auth);
594}
595
596sub _create_proxy_tunnel {
597    my ($self, $request, $handle) = @_;
598
599    $handle->_assert_ssl;
600
601    my $agent = exists($request->{headers}{'user-agent'})
602        ? $request->{headers}{'user-agent'} : $self->{agent};
603
604    my $connect_request = {
605        method    => 'CONNECT',
606        uri       => $request->{host_port},
607        headers   => {
608            host => $request->{host_port},
609            'user-agent' => $agent,
610        }
611    };
612
613    if ( $request->{headers}{'proxy-authorization'} ) {
614        $connect_request->{headers}{'proxy-authorization'} =
615            delete $request->{headers}{'proxy-authorization'};
616    }
617
618    $handle->write_request($connect_request);
619    my $response;
620    do { $response = $handle->read_response_header }
621        until (substr($response->{status},0,1) ne '1');
622
623    # if CONNECT failed, throw the response so it will be
624    # returned from the original request() method;
625    unless (substr($response->{status},0,1) eq '2') {
626        die $response;
627    }
628
629    # tunnel established, so start SSL handshake
630    $handle->start_ssl( $request->{host} );
631
632    return;
633}
634
635sub _prepare_headers_and_cb {
636    my ($self, $request, $args, $url, $auth) = @_;
637
638    for ($self->{default_headers}, $args->{headers}) {
639        next unless defined;
640        while (my ($k, $v) = each %$_) {
641            $request->{headers}{lc $k} = $v;
642        }
643    }
644    $request->{headers}{'host'}         = $request->{host_port};
645    $request->{headers}{'user-agent'} ||= $self->{agent};
646    $request->{headers}{'connection'}   = "close"
647        unless $self->{keep_alive};
648
649    if ( defined $args->{content} ) {
650        if (ref $args->{content} eq 'CODE') {
651            $request->{headers}{'content-type'} ||= "application/octet-stream";
652            $request->{headers}{'transfer-encoding'} = 'chunked'
653              unless $request->{headers}{'content-length'}
654                  || $request->{headers}{'transfer-encoding'};
655            $request->{cb} = $args->{content};
656        }
657        elsif ( length $args->{content} ) {
658            my $content = $args->{content};
659            if ( $] ge '5.008' ) {
660                utf8::downgrade($content, 1)
661                    or die(qq/Wide character in request message body\n/);
662            }
663            $request->{headers}{'content-type'} ||= "application/octet-stream";
664            $request->{headers}{'content-length'} = length $content
665              unless $request->{headers}{'content-length'}
666                  || $request->{headers}{'transfer-encoding'};
667            $request->{cb} = sub { substr $content, 0, length $content, '' };
668        }
669        $request->{trailer_cb} = $args->{trailer_callback}
670            if ref $args->{trailer_callback} eq 'CODE';
671    }
672
673    ### If we have a cookie jar, then maybe add relevant cookies
674    if ( $self->{cookie_jar} ) {
675        my $cookies = $self->cookie_jar->cookie_header( $url );
676        $request->{headers}{cookie} = $cookies if length $cookies;
677    }
678
679    # if we have Basic auth parameters, add them
680    if ( length $auth && ! defined $request->{headers}{authorization} ) {
681        $self->_add_basic_auth_header( $request, 'authorization' => $auth );
682    }
683
684    return;
685}
686
687sub _add_basic_auth_header {
688    my ($self, $request, $header, $auth) = @_;
689    require MIME::Base64;
690    $request->{headers}{$header} =
691        "Basic " . MIME::Base64::encode_base64($auth, "");
692    return;
693}
694
695sub _prepare_data_cb {
696    my ($self, $response, $args) = @_;
697    my $data_cb = $args->{data_callback};
698    $response->{content} = '';
699
700    if (!$data_cb || $response->{status} !~ /^2/) {
701        if (defined $self->{max_size}) {
702            $data_cb = sub {
703                $_[1]->{content} .= $_[0];
704                die(qq/Size of response body exceeds the maximum allowed of $self->{max_size}\n/)
705                  if length $_[1]->{content} > $self->{max_size};
706            };
707        }
708        else {
709            $data_cb = sub { $_[1]->{content} .= $_[0] };
710        }
711    }
712    return $data_cb;
713}
714
715sub _update_cookie_jar {
716    my ($self, $url, $response) = @_;
717
718    my $cookies = $response->{headers}->{'set-cookie'};
719    return unless defined $cookies;
720
721    my @cookies = ref $cookies ? @$cookies : $cookies;
722
723    $self->cookie_jar->add( $url, $_ ) for @cookies;
724
725    return;
726}
727
728sub _validate_cookie_jar {
729    my ($class, $jar) = @_;
730
731    # duck typing
732    for my $method ( qw/add cookie_header/ ) {
733        Carp::croak(qq/Cookie jar must provide the '$method' method\n/)
734            unless ref($jar) && ref($jar)->can($method);
735    }
736
737    return;
738}
739
740sub _maybe_redirect {
741    my ($self, $request, $response, $args) = @_;
742    my $headers = $response->{headers};
743    my ($status, $method) = ($response->{status}, $request->{method});
744    if (($status eq '303' or ($status =~ /^30[127]/ && $method =~ /^GET|HEAD$/))
745        and $headers->{location}
746        and ++$args->{redirects} <= $self->{max_redirect}
747    ) {
748        my $location = ($headers->{location} =~ /^\//)
749            ? "$request->{scheme}://$request->{host_port}$headers->{location}"
750            : $headers->{location} ;
751        return (($status eq '303' ? 'GET' : $method), $location);
752    }
753    return;
754}
755
756sub _split_url {
757    my $url = pop;
758
759    # URI regex adapted from the URI module
760    my ($scheme, $authority, $path_query) = $url =~ m<\A([^:/?#]+)://([^/?#]*)([^#]*)>
761      or die(qq/Cannot parse URL: '$url'\n/);
762
763    $scheme     = lc $scheme;
764    $path_query = "/$path_query" unless $path_query =~ m<\A/>;
765
766    my ($auth,$host);
767    $authority = (length($authority)) ? $authority : 'localhost';
768    if ( $authority =~ /@/ ) {
769        ($auth,$host) = $authority =~ m/\A([^@]*)@(.*)\z/;   # user:pass@host
770        # userinfo might be percent escaped, so recover real auth info
771        $auth =~ s/%([0-9A-Fa-f]{2})/chr(hex($1))/eg;
772    }
773    else {
774        $host = $authority;
775        $auth = '';
776    }
777    $host = lc $host;
778    my $port = do {
779       $host =~ s/:([0-9]*)\z// && length $1
780         ? $1
781         : ($scheme eq 'http' ? 80 : $scheme eq 'https' ? 443 : undef);
782    };
783
784    return ($scheme, $host, $port, $path_query, $auth);
785}
786
787# Date conversions adapted from HTTP::Date
788my $DoW = "Sun|Mon|Tue|Wed|Thu|Fri|Sat";
789my $MoY = "Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec";
790sub _http_date {
791    my ($sec, $min, $hour, $mday, $mon, $year, $wday) = gmtime($_[1]);
792    return sprintf("%s, %02d %s %04d %02d:%02d:%02d GMT",
793        substr($DoW,$wday*4,3),
794        $mday, substr($MoY,$mon*4,3), $year+1900,
795        $hour, $min, $sec
796    );
797}
798
799sub _parse_http_date {
800    my ($self, $str) = @_;
801    require Time::Local;
802    my @tl_parts;
803    if ($str =~ /^[SMTWF][a-z]+, +(\d{1,2}) ($MoY) +(\d\d\d\d) +(\d\d):(\d\d):(\d\d) +GMT$/) {
804        @tl_parts = ($6, $5, $4, $1, (index($MoY,$2)/4), $3);
805    }
806    elsif ($str =~ /^[SMTWF][a-z]+, +(\d\d)-($MoY)-(\d{2,4}) +(\d\d):(\d\d):(\d\d) +GMT$/ ) {
807        @tl_parts = ($6, $5, $4, $1, (index($MoY,$2)/4), $3);
808    }
809    elsif ($str =~ /^[SMTWF][a-z]+ +($MoY) +(\d{1,2}) +(\d\d):(\d\d):(\d\d) +(?:[^0-9]+ +)?(\d\d\d\d)$/ ) {
810        @tl_parts = ($5, $4, $3, $2, (index($MoY,$1)/4), $6);
811    }
812    return eval {
813        my $t = @tl_parts ? Time::Local::timegm(@tl_parts) : -1;
814        $t < 0 ? undef : $t;
815    };
816}
817
818# URI escaping adapted from URI::Escape
819# c.f. http://www.w3.org/TR/html4/interact/forms.html#h-17.13.4.1
820# perl 5.6 ready UTF-8 encoding adapted from JSON::PP
821my %escapes = map { chr($_) => sprintf("%%%02X", $_) } 0..255;
822$escapes{' '}="+";
823my $unsafe_char = qr/[^A-Za-z0-9\-\._~]/;
824
825sub _uri_escape {
826    my ($self, $str) = @_;
827    if ( $] ge '5.008' ) {
828        utf8::encode($str);
829    }
830    else {
831        $str = pack("U*", unpack("C*", $str)) # UTF-8 encode a byte string
832            if ( length $str == do { use bytes; length $str } );
833        $str = pack("C*", unpack("C*", $str)); # clear UTF-8 flag
834    }
835    $str =~ s/($unsafe_char)/$escapes{$1}/ge;
836    return $str;
837}
838
839package
840    HTTP::Tiny::Handle; # hide from PAUSE/indexers
841use strict;
842use warnings;
843
844use Errno      qw[EINTR EPIPE];
845use IO::Socket qw[SOCK_STREAM];
846
847# PERL_HTTP_TINY_IPV4_ONLY is a private environment variable to force old
848# behavior if someone is unable to boostrap CPAN from a new perl install; it is
849# not intended for general, per-client use and may be removed in the future
850my $SOCKET_CLASS =
851    $ENV{PERL_HTTP_TINY_IPV4_ONLY} ? 'IO::Socket::INET' :
852    eval { require IO::Socket::IP; IO::Socket::IP->VERSION(0.25) } ? 'IO::Socket::IP' :
853    'IO::Socket::INET';
854
855sub BUFSIZE () { 32768 } ## no critic
856
857my $Printable = sub {
858    local $_ = shift;
859    s/\r/\\r/g;
860    s/\n/\\n/g;
861    s/\t/\\t/g;
862    s/([^\x20-\x7E])/sprintf('\\x%.2X', ord($1))/ge;
863    $_;
864};
865
866my $Token = qr/[\x21\x23-\x27\x2A\x2B\x2D\x2E\x30-\x39\x41-\x5A\x5E-\x7A\x7C\x7E]/;
867
868sub new {
869    my ($class, %args) = @_;
870    return bless {
871        rbuf             => '',
872        timeout          => 60,
873        max_line_size    => 16384,
874        max_header_lines => 64,
875        verify_SSL       => 0,
876        SSL_options      => {},
877        %args
878    }, $class;
879}
880
881sub connect {
882    @_ == 4 || die(q/Usage: $handle->connect(scheme, host, port)/ . "\n");
883    my ($self, $scheme, $host, $port) = @_;
884
885    if ( $scheme eq 'https' ) {
886        $self->_assert_ssl;
887    }
888    elsif ( $scheme ne 'http' ) {
889      die(qq/Unsupported URL scheme '$scheme'\n/);
890    }
891    $self->{fh} = $SOCKET_CLASS->new(
892        PeerHost  => $host,
893        PeerPort  => $port,
894        $self->{local_address} ?
895            ( LocalAddr => $self->{local_address} ) : (),
896        Proto     => 'tcp',
897        Type      => SOCK_STREAM,
898        Timeout   => $self->{timeout},
899        KeepAlive => !!$self->{keep_alive}
900    ) or die(qq/Could not connect to '$host:$port': $@\n/);
901
902    binmode($self->{fh})
903      or die(qq/Could not binmode() socket: '$!'\n/);
904
905    $self->start_ssl($host) if $scheme eq 'https';
906
907    $self->{scheme} = $scheme;
908    $self->{host} = $host;
909    $self->{port} = $port;
910
911    return $self;
912}
913
914sub start_ssl {
915    my ($self, $host) = @_;
916
917    # As this might be used via CONNECT after an SSL session
918    # to a proxy, we shut down any existing SSL before attempting
919    # the handshake
920    if ( ref($self->{fh}) eq 'IO::Socket::SSL' ) {
921        unless ( $self->{fh}->stop_SSL ) {
922            my $ssl_err = IO::Socket::SSL->errstr;
923            die(qq/Error halting prior SSL connection: $ssl_err/);
924        }
925    }
926
927    my $ssl_args = $self->_ssl_args($host);
928    IO::Socket::SSL->start_SSL(
929        $self->{fh},
930        %$ssl_args,
931        SSL_create_ctx_callback => sub {
932            my $ctx = shift;
933            Net::SSLeay::CTX_set_mode($ctx, Net::SSLeay::MODE_AUTO_RETRY());
934        },
935    );
936
937    unless ( ref($self->{fh}) eq 'IO::Socket::SSL' ) {
938        my $ssl_err = IO::Socket::SSL->errstr;
939        die(qq/SSL connection failed for $host: $ssl_err\n/);
940    }
941}
942
943sub close {
944    @_ == 1 || die(q/Usage: $handle->close()/ . "\n");
945    my ($self) = @_;
946    CORE::close($self->{fh})
947      or die(qq/Could not close socket: '$!'\n/);
948}
949
950sub write {
951    @_ == 2 || die(q/Usage: $handle->write(buf)/ . "\n");
952    my ($self, $buf) = @_;
953
954    if ( $] ge '5.008' ) {
955        utf8::downgrade($buf, 1)
956            or die(qq/Wide character in write()\n/);
957    }
958
959    my $len = length $buf;
960    my $off = 0;
961
962    local $SIG{PIPE} = 'IGNORE';
963
964    while () {
965        $self->can_write
966          or die(qq/Timed out while waiting for socket to become ready for writing\n/);
967        my $r = syswrite($self->{fh}, $buf, $len, $off);
968        if (defined $r) {
969            $len -= $r;
970            $off += $r;
971            last unless $len > 0;
972        }
973        elsif ($! == EPIPE) {
974            die(qq/Socket closed by remote server: $!\n/);
975        }
976        elsif ($! != EINTR) {
977            if ($self->{fh}->can('errstr')){
978                my $err = $self->{fh}->errstr();
979                die (qq/Could not write to SSL socket: '$err'\n /);
980            }
981            else {
982                die(qq/Could not write to socket: '$!'\n/);
983            }
984
985        }
986    }
987    return $off;
988}
989
990sub read {
991    @_ == 2 || @_ == 3 || die(q/Usage: $handle->read(len [, allow_partial])/ . "\n");
992    my ($self, $len, $allow_partial) = @_;
993
994    my $buf  = '';
995    my $got = length $self->{rbuf};
996
997    if ($got) {
998        my $take = ($got < $len) ? $got : $len;
999        $buf  = substr($self->{rbuf}, 0, $take, '');
1000        $len -= $take;
1001    }
1002
1003    while ($len > 0) {
1004        $self->can_read
1005          or die(q/Timed out while waiting for socket to become ready for reading/ . "\n");
1006        my $r = sysread($self->{fh}, $buf, $len, length $buf);
1007        if (defined $r) {
1008            last unless $r;
1009            $len -= $r;
1010        }
1011        elsif ($! != EINTR) {
1012            if ($self->{fh}->can('errstr')){
1013                my $err = $self->{fh}->errstr();
1014                die (qq/Could not read from SSL socket: '$err'\n /);
1015            }
1016            else {
1017                die(qq/Could not read from socket: '$!'\n/);
1018            }
1019        }
1020    }
1021    if ($len && !$allow_partial) {
1022        die(qq/Unexpected end of stream\n/);
1023    }
1024    return $buf;
1025}
1026
1027sub readline {
1028    @_ == 1 || die(q/Usage: $handle->readline()/ . "\n");
1029    my ($self) = @_;
1030
1031    while () {
1032        if ($self->{rbuf} =~ s/\A ([^\x0D\x0A]* \x0D?\x0A)//x) {
1033            return $1;
1034        }
1035        if (length $self->{rbuf} >= $self->{max_line_size}) {
1036            die(qq/Line size exceeds the maximum allowed size of $self->{max_line_size}\n/);
1037        }
1038        $self->can_read
1039          or die(qq/Timed out while waiting for socket to become ready for reading\n/);
1040        my $r = sysread($self->{fh}, $self->{rbuf}, BUFSIZE, length $self->{rbuf});
1041        if (defined $r) {
1042            last unless $r;
1043        }
1044        elsif ($! != EINTR) {
1045            if ($self->{fh}->can('errstr')){
1046                my $err = $self->{fh}->errstr();
1047                die (qq/Could not read from SSL socket: '$err'\n /);
1048            }
1049            else {
1050                die(qq/Could not read from socket: '$!'\n/);
1051            }
1052        }
1053    }
1054    die(qq/Unexpected end of stream while looking for line\n/);
1055}
1056
1057sub read_header_lines {
1058    @_ == 1 || @_ == 2 || die(q/Usage: $handle->read_header_lines([headers])/ . "\n");
1059    my ($self, $headers) = @_;
1060    $headers ||= {};
1061    my $lines   = 0;
1062    my $val;
1063
1064    while () {
1065         my $line = $self->readline;
1066
1067         if (++$lines >= $self->{max_header_lines}) {
1068             die(qq/Header lines exceeds maximum number allowed of $self->{max_header_lines}\n/);
1069         }
1070         elsif ($line =~ /\A ([^\x00-\x1F\x7F:]+) : [\x09\x20]* ([^\x0D\x0A]*)/x) {
1071             my ($field_name) = lc $1;
1072             if (exists $headers->{$field_name}) {
1073                 for ($headers->{$field_name}) {
1074                     $_ = [$_] unless ref $_ eq "ARRAY";
1075                     push @$_, $2;
1076                     $val = \$_->[-1];
1077                 }
1078             }
1079             else {
1080                 $val = \($headers->{$field_name} = $2);
1081             }
1082         }
1083         elsif ($line =~ /\A [\x09\x20]+ ([^\x0D\x0A]*)/x) {
1084             $val
1085               or die(qq/Unexpected header continuation line\n/);
1086             next unless length $1;
1087             $$val .= ' ' if length $$val;
1088             $$val .= $1;
1089         }
1090         elsif ($line =~ /\A \x0D?\x0A \z/x) {
1091            last;
1092         }
1093         else {
1094            die(q/Malformed header line: / . $Printable->($line) . "\n");
1095         }
1096    }
1097    return $headers;
1098}
1099
1100sub write_request {
1101    @_ == 2 || die(q/Usage: $handle->write_request(request)/ . "\n");
1102    my($self, $request) = @_;
1103    $self->write_request_header(@{$request}{qw/method uri headers/});
1104    $self->write_body($request) if $request->{cb};
1105    return;
1106}
1107
1108my %HeaderCase = (
1109    'content-md5'      => 'Content-MD5',
1110    'etag'             => 'ETag',
1111    'te'               => 'TE',
1112    'www-authenticate' => 'WWW-Authenticate',
1113    'x-xss-protection' => 'X-XSS-Protection',
1114);
1115
1116# to avoid multiple small writes and hence nagle, you can pass the method line or anything else to
1117# combine writes.
1118sub write_header_lines {
1119    (@_ == 2 || @_ == 3 && ref $_[1] eq 'HASH') || die(q/Usage: $handle->write_header_lines(headers[,prefix])/ . "\n");
1120    my($self, $headers, $prefix_data) = @_;
1121
1122    my $buf = (defined $prefix_data ? $prefix_data : '');
1123    while (my ($k, $v) = each %$headers) {
1124        my $field_name = lc $k;
1125        if (exists $HeaderCase{$field_name}) {
1126            $field_name = $HeaderCase{$field_name};
1127        }
1128        else {
1129            $field_name =~ /\A $Token+ \z/xo
1130              or die(q/Invalid HTTP header field name: / . $Printable->($field_name) . "\n");
1131            $field_name =~ s/\b(\w)/\u$1/g;
1132            $HeaderCase{lc $field_name} = $field_name;
1133        }
1134        for (ref $v eq 'ARRAY' ? @$v : $v) {
1135            /[^\x0D\x0A]/
1136              or die(qq/Invalid HTTP header field value ($field_name): / . $Printable->($_). "\n");
1137            $buf .= "$field_name: $_\x0D\x0A";
1138        }
1139    }
1140    $buf .= "\x0D\x0A";
1141    return $self->write($buf);
1142}
1143
1144# return value indicates whether message length was defined; this is generally
1145# true unless there was no content-length header and we just read until EOF.
1146# Other message length errors are thrown as exceptions
1147sub read_body {
1148    @_ == 3 || die(q/Usage: $handle->read_body(callback, response)/ . "\n");
1149    my ($self, $cb, $response) = @_;
1150    my $te = $response->{headers}{'transfer-encoding'} || '';
1151    my $chunked = grep { /chunked/i } ( ref $te eq 'ARRAY' ? @$te : $te ) ;
1152    return $chunked
1153        ? $self->read_chunked_body($cb, $response)
1154        : $self->read_content_body($cb, $response);
1155}
1156
1157sub write_body {
1158    @_ == 2 || die(q/Usage: $handle->write_body(request)/ . "\n");
1159    my ($self, $request) = @_;
1160    if ($request->{headers}{'content-length'}) {
1161        return $self->write_content_body($request);
1162    }
1163    else {
1164        return $self->write_chunked_body($request);
1165    }
1166}
1167
1168sub read_content_body {
1169    @_ == 3 || @_ == 4 || die(q/Usage: $handle->read_content_body(callback, response, [read_length])/ . "\n");
1170    my ($self, $cb, $response, $content_length) = @_;
1171    $content_length ||= $response->{headers}{'content-length'};
1172
1173    if ( defined $content_length ) {
1174        my $len = $content_length;
1175        while ($len > 0) {
1176            my $read = ($len > BUFSIZE) ? BUFSIZE : $len;
1177            $cb->($self->read($read, 0), $response);
1178            $len -= $read;
1179        }
1180        return length($self->{rbuf}) == 0;
1181    }
1182
1183    my $chunk;
1184    $cb->($chunk, $response) while length( $chunk = $self->read(BUFSIZE, 1) );
1185
1186    return;
1187}
1188
1189sub write_content_body {
1190    @_ == 2 || die(q/Usage: $handle->write_content_body(request)/ . "\n");
1191    my ($self, $request) = @_;
1192
1193    my ($len, $content_length) = (0, $request->{headers}{'content-length'});
1194    while () {
1195        my $data = $request->{cb}->();
1196
1197        defined $data && length $data
1198          or last;
1199
1200        if ( $] ge '5.008' ) {
1201            utf8::downgrade($data, 1)
1202                or die(qq/Wide character in write_content()\n/);
1203        }
1204
1205        $len += $self->write($data);
1206    }
1207
1208    $len == $content_length
1209      or die(qq/Content-Length missmatch (got: $len expected: $content_length)\n/);
1210
1211    return $len;
1212}
1213
1214sub read_chunked_body {
1215    @_ == 3 || die(q/Usage: $handle->read_chunked_body(callback, $response)/ . "\n");
1216    my ($self, $cb, $response) = @_;
1217
1218    while () {
1219        my $head = $self->readline;
1220
1221        $head =~ /\A ([A-Fa-f0-9]+)/x
1222          or die(q/Malformed chunk head: / . $Printable->($head) . "\n");
1223
1224        my $len = hex($1)
1225          or last;
1226
1227        $self->read_content_body($cb, $response, $len);
1228
1229        $self->read(2) eq "\x0D\x0A"
1230          or die(qq/Malformed chunk: missing CRLF after chunk data\n/);
1231    }
1232    $self->read_header_lines($response->{headers});
1233    return 1;
1234}
1235
1236sub write_chunked_body {
1237    @_ == 2 || die(q/Usage: $handle->write_chunked_body(request)/ . "\n");
1238    my ($self, $request) = @_;
1239
1240    my $len = 0;
1241    while () {
1242        my $data = $request->{cb}->();
1243
1244        defined $data && length $data
1245          or last;
1246
1247        if ( $] ge '5.008' ) {
1248            utf8::downgrade($data, 1)
1249                or die(qq/Wide character in write_chunked_body()\n/);
1250        }
1251
1252        $len += length $data;
1253
1254        my $chunk  = sprintf '%X', length $data;
1255           $chunk .= "\x0D\x0A";
1256           $chunk .= $data;
1257           $chunk .= "\x0D\x0A";
1258
1259        $self->write($chunk);
1260    }
1261    $self->write("0\x0D\x0A");
1262    $self->write_header_lines($request->{trailer_cb}->())
1263        if ref $request->{trailer_cb} eq 'CODE';
1264    return $len;
1265}
1266
1267sub read_response_header {
1268    @_ == 1 || die(q/Usage: $handle->read_response_header()/ . "\n");
1269    my ($self) = @_;
1270
1271    my $line = $self->readline;
1272
1273    $line =~ /\A (HTTP\/(0*\d+\.0*\d+)) [\x09\x20]+ ([0-9]{3}) [\x09\x20]+ ([^\x0D\x0A]*) \x0D?\x0A/x
1274      or die(q/Malformed Status-Line: / . $Printable->($line). "\n");
1275
1276    my ($protocol, $version, $status, $reason) = ($1, $2, $3, $4);
1277
1278    die (qq/Unsupported HTTP protocol: $protocol\n/)
1279        unless $version =~ /0*1\.0*[01]/;
1280
1281    return {
1282        status       => $status,
1283        reason       => $reason,
1284        headers      => $self->read_header_lines,
1285        protocol     => $protocol,
1286    };
1287}
1288
1289sub write_request_header {
1290    @_ == 4 || die(q/Usage: $handle->write_request_header(method, request_uri, headers)/ . "\n");
1291    my ($self, $method, $request_uri, $headers) = @_;
1292
1293    return $self->write_header_lines($headers, "$method $request_uri HTTP/1.1\x0D\x0A");
1294}
1295
1296sub _do_timeout {
1297    my ($self, $type, $timeout) = @_;
1298    $timeout = $self->{timeout}
1299        unless defined $timeout && $timeout >= 0;
1300
1301    my $fd = fileno $self->{fh};
1302    defined $fd && $fd >= 0
1303      or die(qq/select(2): 'Bad file descriptor'\n/);
1304
1305    my $initial = time;
1306    my $pending = $timeout;
1307    my $nfound;
1308
1309    vec(my $fdset = '', $fd, 1) = 1;
1310
1311    while () {
1312        $nfound = ($type eq 'read')
1313            ? select($fdset, undef, undef, $pending)
1314            : select(undef, $fdset, undef, $pending) ;
1315        if ($nfound == -1) {
1316            $! == EINTR
1317              or die(qq/select(2): '$!'\n/);
1318            redo if !$timeout || ($pending = $timeout - (time - $initial)) > 0;
1319            $nfound = 0;
1320        }
1321        last;
1322    }
1323    $! = 0;
1324    return $nfound;
1325}
1326
1327sub can_read {
1328    @_ == 1 || @_ == 2 || die(q/Usage: $handle->can_read([timeout])/ . "\n");
1329    my $self = shift;
1330    if ( ref($self->{fh}) eq 'IO::Socket::SSL' ) {
1331        return 1 if $self->{fh}->pending;
1332    }
1333    return $self->_do_timeout('read', @_)
1334}
1335
1336sub can_write {
1337    @_ == 1 || @_ == 2 || die(q/Usage: $handle->can_write([timeout])/ . "\n");
1338    my $self = shift;
1339    return $self->_do_timeout('write', @_)
1340}
1341
1342sub _assert_ssl {
1343    # Need IO::Socket::SSL 1.42 for SSL_create_ctx_callback
1344    die(qq/IO::Socket::SSL 1.42 must be installed for https support\n/)
1345        unless eval {require IO::Socket::SSL; IO::Socket::SSL->VERSION(1.42)};
1346    # Need Net::SSLeay 1.49 for MODE_AUTO_RETRY
1347    die(qq/Net::SSLeay 1.49 must be installed for https support\n/)
1348        unless eval {require Net::SSLeay; Net::SSLeay->VERSION(1.49)};
1349}
1350
1351sub can_reuse {
1352    my ($self,$scheme,$host,$port) = @_;
1353    return 0 if
1354         length($self->{rbuf})
1355        || $scheme ne $self->{scheme}
1356        || $host ne $self->{host}
1357        || $port ne $self->{port}
1358        || eval { $self->can_read(0) }
1359        || $@ ;
1360        return 1;
1361}
1362
1363# Try to find a CA bundle to validate the SSL cert,
1364# prefer Mozilla::CA or fallback to a system file
1365sub _find_CA_file {
1366    my $self = shift();
1367
1368    return $self->{SSL_options}->{SSL_ca_file}
1369        if $self->{SSL_options}->{SSL_ca_file} and -e $self->{SSL_options}->{SSL_ca_file};
1370
1371    return Mozilla::CA::SSL_ca_file()
1372        if eval { require Mozilla::CA };
1373
1374    foreach my $ca_bundle (qw{
1375        /etc/ssl/certs/ca-certificates.crt
1376        /etc/pki/tls/certs/ca-bundle.crt
1377        /etc/ssl/ca-bundle.pem
1378        }
1379    ) {
1380        return $ca_bundle if -e $ca_bundle;
1381    }
1382
1383    die qq/Couldn't find a CA bundle with which to verify the SSL certificate.\n/
1384      . qq/Try installing Mozilla::CA from CPAN\n/;
1385}
1386
1387sub _ssl_args {
1388    my ($self, $host) = @_;
1389
1390    my %ssl_args;
1391
1392    # This test reimplements IO::Socket::SSL::can_client_sni(), which wasn't
1393    # added until IO::Socket::SSL 1.84
1394    if ( Net::SSLeay::OPENSSL_VERSION_NUMBER() >= 0x01000000 ) {
1395        $ssl_args{SSL_hostname} = $host,          # Sane SNI support
1396    }
1397
1398    if ($self->{verify_SSL}) {
1399        $ssl_args{SSL_verifycn_scheme}  = 'http'; # enable CN validation
1400        $ssl_args{SSL_verifycn_name}    = $host;  # set validation hostname
1401        $ssl_args{SSL_verify_mode}      = 0x01;   # enable cert validation
1402        $ssl_args{SSL_ca_file}          = $self->_find_CA_file;
1403    }
1404    else {
1405        $ssl_args{SSL_verifycn_scheme}  = 'none'; # disable CN validation
1406        $ssl_args{SSL_verify_mode}      = 0x00;   # disable cert validation
1407    }
1408
1409    # user options override settings from verify_SSL
1410    for my $k ( keys %{$self->{SSL_options}} ) {
1411        $ssl_args{$k} = $self->{SSL_options}{$k} if $k =~ m/^SSL_/;
1412    }
1413
1414    return \%ssl_args;
1415}
1416
14171;
1418
1419__END__
1420
1421=pod
1422
1423=encoding UTF-8
1424
1425=head1 NAME
1426
1427HTTP::Tiny - A small, simple, correct HTTP/1.1 client
1428
1429=head1 VERSION
1430
1431version 0.043
1432
1433=head1 SYNOPSIS
1434
1435    use HTTP::Tiny;
1436
1437    my $response = HTTP::Tiny->new->get('http://example.com/');
1438
1439    die "Failed!\n" unless $response->{success};
1440
1441    print "$response->{status} $response->{reason}\n";
1442
1443    while (my ($k, $v) = each %{$response->{headers}}) {
1444        for (ref $v eq 'ARRAY' ? @$v : $v) {
1445            print "$k: $_\n";
1446        }
1447    }
1448
1449    print $response->{content} if length $response->{content};
1450
1451=head1 DESCRIPTION
1452
1453This is a very simple HTTP/1.1 client, designed for doing simple
1454requests without the overhead of a large framework like L<LWP::UserAgent>.
1455
1456It is more correct and more complete than L<HTTP::Lite>.  It supports
1457proxies and redirection.  It also correctly resumes after EINTR.
1458
1459If L<IO::Socket::IP> 0.25 or later is installed, HTTP::Tiny will use it instead
1460of L<IO::Socket::INET> for transparent support for both IPv4 and IPv6.
1461
1462Cookie support requires L<HTTP::CookieJar> or an equivalent class.
1463
1464=head1 METHODS
1465
1466=head2 new
1467
1468    $http = HTTP::Tiny->new( %attributes );
1469
1470This constructor returns a new HTTP::Tiny object.  Valid attributes include:
1471
1472=over 4
1473
1474=item *
1475
1476C<agent>
1477
1478A user-agent string (defaults to 'HTTP-Tiny/$VERSION'). If C<agent> ends in a space character, the default user-agent string is appended.
1479
1480=item *
1481
1482C<cookie_jar>
1483
1484An instance of L<HTTP::CookieJar> or equivalent class that supports the C<add> and C<cookie_header> methods
1485
1486=item *
1487
1488C<default_headers>
1489
1490A hashref of default headers to apply to requests
1491
1492=item *
1493
1494C<local_address>
1495
1496The local IP address to bind to
1497
1498=item *
1499
1500C<keep_alive>
1501
1502Whether to reuse the last connection (if for the same scheme, host and port) (defaults to 1)
1503
1504=item *
1505
1506C<max_redirect>
1507
1508Maximum number of redirects allowed (defaults to 5)
1509
1510=item *
1511
1512C<max_size>
1513
1514Maximum response size (only when not using a data callback).  If defined, responses larger than this will return an exception.
1515
1516=item *
1517
1518C<http_proxy>
1519
1520URL of a proxy server to use for HTTP connections (default is C<$ENV{http_proxy}> if set)
1521
1522=item *
1523
1524C<https_proxy>
1525
1526URL of a proxy server to use for HTTPS connections (default is C<$ENV{https_proxy}> if set)
1527
1528=item *
1529
1530C<proxy>
1531
1532URL of a generic proxy server for both HTTP and HTTPS connections (default is C<$ENV{all_proxy}> if set)
1533
1534=item *
1535
1536C<no_proxy>
1537
1538List of domain suffixes that should not be proxied.  Must be a comma-separated string or an array reference. (default is C<$ENV{no_proxy}>)
1539
1540=item *
1541
1542C<timeout>
1543
1544Request timeout in seconds (default is 60)
1545
1546=item *
1547
1548C<verify_SSL>
1549
1550A boolean that indicates whether to validate the SSL certificate of an C<https>
1551connection (default is false)
1552
1553=item *
1554
1555C<SSL_options>
1556
1557A hashref of C<SSL_*> options to pass through to L<IO::Socket::SSL>
1558
1559=back
1560
1561Exceptions from C<max_size>, C<timeout> or other errors will result in a
1562pseudo-HTTP status code of 599 and a reason of "Internal Exception". The
1563content field in the response will contain the text of the exception.
1564
1565The C<keep_alive> parameter enables a persistent connection, but only to a
1566single destination scheme, host and port.  Also, if any connection-relevant
1567attributes are modified, a persistent connection will be dropped.  If you want
1568persistent connections across multiple destinations, use multiple HTTP::Tiny
1569objects.
1570
1571See L</SSL SUPPORT> for more on the C<verify_SSL> and C<SSL_options> attributes.
1572
1573=head2 get|head|put|post|delete
1574
1575    $response = $http->get($url);
1576    $response = $http->get($url, \%options);
1577    $response = $http->head($url);
1578
1579These methods are shorthand for calling C<request()> for the given method.  The
1580URL must have unsafe characters escaped and international domain names encoded.
1581See C<request()> for valid options and a description of the response.
1582
1583The C<success> field of the response will be true if the status code is 2XX.
1584
1585=head2 post_form
1586
1587    $response = $http->post_form($url, $form_data);
1588    $response = $http->post_form($url, $form_data, \%options);
1589
1590This method executes a C<POST> request and sends the key/value pairs from a
1591form data hash or array reference to the given URL with a C<content-type> of
1592C<application/x-www-form-urlencoded>.  If data is provided as an array
1593reference, the order is preserved; if provided as a hash reference, the terms
1594are sorted on key and value for consistency.  See documentation for the
1595C<www_form_urlencode> method for details on the encoding.
1596
1597The URL must have unsafe characters escaped and international domain names
1598encoded.  See C<request()> for valid options and a description of the response.
1599Any C<content-type> header or content in the options hashref will be ignored.
1600
1601The C<success> field of the response will be true if the status code is 2XX.
1602
1603=head2 mirror
1604
1605    $response = $http->mirror($url, $file, \%options)
1606    if ( $response->{success} ) {
1607        print "$file is up to date\n";
1608    }
1609
1610Executes a C<GET> request for the URL and saves the response body to the file
1611name provided.  The URL must have unsafe characters escaped and international
1612domain names encoded.  If the file already exists, the request will include an
1613C<If-Modified-Since> header with the modification timestamp of the file.  You
1614may specify a different C<If-Modified-Since> header yourself in the C<<
1615$options->{headers} >> hash.
1616
1617The C<success> field of the response will be true if the status code is 2XX
1618or if the status code is 304 (unmodified).
1619
1620If the file was modified and the server response includes a properly
1621formatted C<Last-Modified> header, the file modification time will
1622be updated accordingly.
1623
1624=head2 request
1625
1626    $response = $http->request($method, $url);
1627    $response = $http->request($method, $url, \%options);
1628
1629Executes an HTTP request of the given method type ('GET', 'HEAD', 'POST',
1630'PUT', etc.) on the given URL.  The URL must have unsafe characters escaped and
1631international domain names encoded.
1632
1633If the URL includes a "user:password" stanza, they will be used for Basic-style
1634authorization headers.  (Authorization headers will not be included in a
1635redirected request.) For example:
1636
1637    $http->request('GET', 'http://Aladdin:open sesame@example.com/');
1638
1639If the "user:password" stanza contains reserved characters, they must
1640be percent-escaped:
1641
1642    $http->request('GET', 'http://john%40example.com:password@example.com/');
1643
1644A hashref of options may be appended to modify the request.
1645
1646Valid options are:
1647
1648=over 4
1649
1650=item *
1651
1652C<headers>
1653
1654A hashref containing headers to include with the request.  If the value for
1655a header is an array reference, the header will be output multiple times with
1656each value in the array.  These headers over-write any default headers.
1657
1658=item *
1659
1660C<content>
1661
1662A scalar to include as the body of the request OR a code reference
1663that will be called iteratively to produce the body of the request
1664
1665=item *
1666
1667C<trailer_callback>
1668
1669A code reference that will be called if it exists to provide a hashref
1670of trailing headers (only used with chunked transfer-encoding)
1671
1672=item *
1673
1674C<data_callback>
1675
1676A code reference that will be called for each chunks of the response
1677body received.
1678
1679=back
1680
1681If the C<content> option is a code reference, it will be called iteratively
1682to provide the content body of the request.  It should return the empty
1683string or undef when the iterator is exhausted.
1684
1685If the C<content> option is the empty string, no C<content-type> or
1686C<content-length> headers will be generated.
1687
1688If the C<data_callback> option is provided, it will be called iteratively until
1689the entire response body is received.  The first argument will be a string
1690containing a chunk of the response body, the second argument will be the
1691in-progress response hash reference, as described below.  (This allows
1692customizing the action of the callback based on the C<status> or C<headers>
1693received prior to the content body.)
1694
1695The C<request> method returns a hashref containing the response.  The hashref
1696will have the following keys:
1697
1698=over 4
1699
1700=item *
1701
1702C<success>
1703
1704Boolean indicating whether the operation returned a 2XX status code
1705
1706=item *
1707
1708C<url>
1709
1710URL that provided the response. This is the URL of the request unless
1711there were redirections, in which case it is the last URL queried
1712in a redirection chain
1713
1714=item *
1715
1716C<status>
1717
1718The HTTP status code of the response
1719
1720=item *
1721
1722C<reason>
1723
1724The response phrase returned by the server
1725
1726=item *
1727
1728C<content>
1729
1730The body of the response.  If the response does not have any content
1731or if a data callback is provided to consume the response body,
1732this will be the empty string
1733
1734=item *
1735
1736C<headers>
1737
1738A hashref of header fields.  All header field names will be normalized
1739to be lower case. If a header is repeated, the value will be an arrayref;
1740it will otherwise be a scalar string containing the value
1741
1742=back
1743
1744On an exception during the execution of the request, the C<status> field will
1745contain 599, and the C<content> field will contain the text of the exception.
1746
1747=head2 www_form_urlencode
1748
1749    $params = $http->www_form_urlencode( $data );
1750    $response = $http->get("http://example.com/query?$params");
1751
1752This method converts the key/value pairs from a data hash or array reference
1753into a C<x-www-form-urlencoded> string.  The keys and values from the data
1754reference will be UTF-8 encoded and escaped per RFC 3986.  If a value is an
1755array reference, the key will be repeated with each of the values of the array
1756reference.  If data is provided as a hash reference, the key/value pairs in the
1757resulting string will be sorted by key and value for consistent ordering.
1758
1759=for Pod::Coverage SSL_options
1760agent
1761cookie_jar
1762default_headers
1763http_proxy
1764https_proxy
1765keep_alive
1766local_address
1767max_redirect
1768max_size
1769no_proxy
1770proxy
1771timeout
1772verify_SSL
1773
1774=head1 SSL SUPPORT
1775
1776Direct C<https> connections are supported only if L<IO::Socket::SSL> 1.56 or
1777greater and L<Net::SSLeay> 1.49 or greater are installed. An exception will be
1778thrown if a new enough versions of these modules not installed or if the SSL
1779encryption fails. An C<https> connection may be made via an C<http> proxy that
1780supports the CONNECT command (i.e. RFC 2817).  You may not proxy C<https> via
1781a proxy that itself requires C<https> to communicate.
1782
1783SSL provides two distinct capabilities:
1784
1785=over 4
1786
1787=item *
1788
1789Encrypted communication channel
1790
1791=item *
1792
1793Verification of server identity
1794
1795=back
1796
1797B<By default, HTTP::Tiny does not verify server identity>.
1798
1799Server identity verification is controversial and potentially tricky because it
1800depends on a (usually paid) third-party Certificate Authority (CA) trust model
1801to validate a certificate as legitimate.  This discriminates against servers
1802with self-signed certificates or certificates signed by free, community-driven
1803CA's such as L<CAcert.org|http://cacert.org>.
1804
1805By default, HTTP::Tiny does not make any assumptions about your trust model,
1806threat level or risk tolerance.  It just aims to give you an encrypted channel
1807when you need one.
1808
1809Setting the C<verify_SSL> attribute to a true value will make HTTP::Tiny verify
1810that an SSL connection has a valid SSL certificate corresponding to the host
1811name of the connection and that the SSL certificate has been verified by a CA.
1812Assuming you trust the CA, this will protect against a L<man-in-the-middle
1813attack|http://en.wikipedia.org/wiki/Man-in-the-middle_attack>.  If you are
1814concerned about security, you should enable this option.
1815
1816Certificate verification requires a file containing trusted CA certificates.
1817If the L<Mozilla::CA> module is installed, HTTP::Tiny will use the CA file
1818included with it as a source of trusted CA's.  (This means you trust Mozilla,
1819the author of Mozilla::CA, the CPAN mirror where you got Mozilla::CA, the
1820toolchain used to install it, and your operating system security, right?)
1821
1822If that module is not available, then HTTP::Tiny will search several
1823system-specific default locations for a CA certificate file:
1824
1825=over 4
1826
1827=item *
1828
1829/etc/ssl/certs/ca-certificates.crt
1830
1831=item *
1832
1833/etc/pki/tls/certs/ca-bundle.crt
1834
1835=item *
1836
1837/etc/ssl/ca-bundle.pem
1838
1839=back
1840
1841An exception will be raised if C<verify_SSL> is true and no CA certificate file
1842is available.
1843
1844If you desire complete control over SSL connections, the C<SSL_options> attribute
1845lets you provide a hash reference that will be passed through to
1846C<IO::Socket::SSL::start_SSL()>, overriding any options set by HTTP::Tiny. For
1847example, to provide your own trusted CA file:
1848
1849    SSL_options => {
1850        SSL_ca_file => $file_path,
1851    }
1852
1853The C<SSL_options> attribute could also be used for such things as providing a
1854client certificate for authentication to a server or controlling the choice of
1855cipher used for the SSL connection. See L<IO::Socket::SSL> documentation for
1856details.
1857
1858=head1 PROXY SUPPORT
1859
1860HTTP::Tiny can proxy both C<http> and C<https> requests.  Only Basic proxy
1861authorization is supported and it must be provided as part of the proxy URL:
1862C<http://user:pass@proxy.example.com/>.
1863
1864HTTP::Tiny supports the following proxy environment variables:
1865
1866=over 4
1867
1868=item *
1869
1870http_proxy
1871
1872=item *
1873
1874https_proxy or HTTPS_PROXY
1875
1876=item *
1877
1878all_proxy or ALL_PROXY
1879
1880=back
1881
1882Tunnelling C<https> over an C<http> proxy using the CONNECT method is
1883supported.  If your proxy uses C<https> itself, you can not tunnel C<https>
1884over it.
1885
1886Be warned that proxying an C<https> connection opens you to the risk of a
1887man-in-the-middle attack by the proxy server.
1888
1889The C<no_proxy> environment variable is supported in the format of a
1890comma-separated list of domain extensions proxy should not be used for.
1891
1892Proxy arguments passed to C<new> will override their corresponding
1893environment variables.
1894
1895=head1 LIMITATIONS
1896
1897HTTP::Tiny is I<conditionally compliant> with the
1898L<HTTP/1.1 specification|http://www.w3.org/Protocols/rfc2616/rfc2616.html>.
1899It attempts to meet all "MUST" requirements of the specification, but does not
1900implement all "SHOULD" requirements.
1901
1902Some particular limitations of note include:
1903
1904=over
1905
1906=item *
1907
1908HTTP::Tiny focuses on correct transport.  Users are responsible for ensuring
1909that user-defined headers and content are compliant with the HTTP/1.1
1910specification.
1911
1912=item *
1913
1914Users must ensure that URLs are properly escaped for unsafe characters and that
1915international domain names are properly encoded to ASCII. See L<URI::Escape>,
1916L<URI::_punycode> and L<Net::IDN::Encode>.
1917
1918=item *
1919
1920Redirection is very strict against the specification.  Redirection is only
1921automatic for response codes 301, 302 and 307 if the request method is 'GET' or
1922'HEAD'.  Response code 303 is always converted into a 'GET' redirection, as
1923mandated by the specification.  There is no automatic support for status 305
1924("Use proxy") redirections.
1925
1926=item *
1927
1928There is no provision for delaying a request body using an C<Expect> header.
1929Unexpected C<1XX> responses are silently ignored as per the specification.
1930
1931=item *
1932
1933Only 'chunked' C<Transfer-Encoding> is supported.
1934
1935=item *
1936
1937There is no support for a Request-URI of '*' for the 'OPTIONS' request.
1938
1939=back
1940
1941Despite the limitations listed above, HTTP::Tiny is considered
1942feature-complete.  New feature requests should be directed to
1943L<HTTP::Tiny::UA>.
1944
1945=head1 SEE ALSO
1946
1947=over 4
1948
1949=item *
1950
1951L<HTTP::Tiny::UA> - Higher level UA features for HTTP::Tiny
1952
1953=item *
1954
1955L<HTTP::Thin> - HTTP::Tiny wrapper with L<HTTP::Request>/L<HTTP::Response> compatibility
1956
1957=item *
1958
1959L<HTTP::Tiny::Mech> - Wrap L<WWW::Mechanize> instance in HTTP::Tiny compatible interface
1960
1961=item *
1962
1963L<IO::Socket::IP> - Required for IPv6 support
1964
1965=item *
1966
1967L<IO::Socket::SSL> - Required for SSL support
1968
1969=item *
1970
1971L<LWP::UserAgent> - If HTTP::Tiny isn't enough for you, this is the "standard" way to do things
1972
1973=item *
1974
1975L<Mozilla::CA> - Required if you want to validate SSL certificates
1976
1977=item *
1978
1979L<Net::SSLeay> - Required for SSL support
1980
1981=back
1982
1983=for :stopwords cpan testmatrix url annocpan anno bugtracker rt cpants kwalitee diff irc mailto metadata placeholders metacpan
1984
1985=head1 SUPPORT
1986
1987=head2 Bugs / Feature Requests
1988
1989Please report any bugs or feature requests through the issue tracker
1990at L<https://github.com/chansen/p5-http-tiny/issues>.
1991You will be notified automatically of any progress on your issue.
1992
1993=head2 Source Code
1994
1995This is open source software.  The code repository is available for
1996public review and contribution under the terms of the license.
1997
1998L<https://github.com/chansen/p5-http-tiny>
1999
2000  git clone https://github.com/chansen/p5-http-tiny.git
2001
2002=head1 AUTHORS
2003
2004=over 4
2005
2006=item *
2007
2008Christian Hansen <chansen@cpan.org>
2009
2010=item *
2011
2012David Golden <dagolden@cpan.org>
2013
2014=back
2015
2016=head1 CONTRIBUTORS
2017
2018=over 4
2019
2020=item *
2021
2022Alan Gardner <gardner@pythian.com>
2023
2024=item *
2025
2026Alessandro Ghedini <al3xbio@gmail.com>
2027
2028=item *
2029
2030Brad Gilbert <bgills@cpan.org>
2031
2032=item *
2033
2034Chris Nehren <apeiron@cpan.org>
2035
2036=item *
2037
2038Chris Weyl <cweyl@alumni.drew.edu>
2039
2040=item *
2041
2042Claes Jakobsson <claes@surfar.nu>
2043
2044=item *
2045
2046Clinton Gormley <clint@traveljury.com>
2047
2048=item *
2049
2050Craig Berry <cberry@cpan.org>
2051
2052=item *
2053
2054David Mitchell <davem@iabyn.com>
2055
2056=item *
2057
2058Edward Zborowski <ed@rubensteintech.com>
2059
2060=item *
2061
2062Jess Robinson <castaway@desert-island.me.uk>
2063
2064=item *
2065
2066Lukas Eklund <leklund@gmail.com>
2067
2068=item *
2069
2070Martin J. Evans <mjegh@ntlworld.com>
2071
2072=item *
2073
2074Martin-Louis Bright <mlbright@gmail.com>
2075
2076=item *
2077
2078Mike Doherty <doherty@cpan.org>
2079
2080=item *
2081
2082Petr Písař <ppisar@redhat.com>
2083
2084=item *
2085
2086Serguei Trouchelle <stro@cpan.org>
2087
2088=item *
2089
2090Syohei YOSHIDA <syohex@gmail.com>
2091
2092=item *
2093
2094Tony Cook <tony@develop-help.com>
2095
2096=back
2097
2098=head1 COPYRIGHT AND LICENSE
2099
2100This software is copyright (c) 2014 by Christian Hansen.
2101
2102This is free software; you can redistribute it and/or modify it under
2103the same terms as the Perl 5 programming language system itself.
2104
2105=cut
2106