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