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