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