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