1 # vim: ts=4 sts=4 sw=4 et:
5 # ABSTRACT: A small, simple, correct HTTP/1.1 client
6 our $VERSION = '0.043'; # VERSION
12 # $http = HTTP::Tiny->new( %attributes );
14 # This constructor returns a new HTTP::Tiny object. Valid attributes include:
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.
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
24 # The local IP address to bind to
26 # Whether to reuse the last connection (if for the same scheme, host and port) (defaults to 1)
28 # Maximum number of redirects allowed (defaults to 5)
30 # Maximum response size (only when not using a data callback). If defined, responses larger than this will return an exception.
32 # URL of a proxy server to use for HTTP connections (default is C<$ENV{http_proxy}> if set)
34 # URL of a proxy server to use for HTTPS connections (default is C<$ENV{https_proxy}> if set)
36 # URL of a generic proxy server for both HTTP and HTTPS connections (default is C<$ENV{all_proxy}> if set)
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}>)
40 # Request timeout in seconds (default is 60)
42 # A boolean that indicates whether to validate the SSL certificate of an C<https>
43 # connection (default is false)
45 # A hashref of C<SSL_*> options to pass through to L<IO::Socket::SSL>
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.
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
57 # See L</SSL SUPPORT> for more on the C<verify_SSL> and C<SSL_options> attributes.
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
68 my %persist_ok = map {; $_ => 1 } qw(
69 cookie_jar default_headers max_redirect max_size
72 no warnings 'uninitialized';
73 for my $accessor ( @attributes ) {
77 delete $_[0]->{handle} if !$persist_ok{$accessor} && $_[1] ne $_[0]->{$accessor};
78 $_[0]->{$accessor} = $_[1]
86 my($self, $agent) = @_;
89 (defined $agent && $agent =~ / $/) ? $agent . $self->_agent : $agent;
91 return $self->{agent};
95 my($class, %args) = @_;
101 verify_SSL => $args{verify_SSL} || $args{verify_ssl} || 0, # no verification by default
102 no_proxy => $ENV{no_proxy},
107 $class->_validate_cookie_jar( $args{cookie_jar} ) if $args{cookie_jar};
109 for my $key ( @attributes ) {
110 $self->{$key} = $args{$key} if exists $args{$key}
113 $self->agent( exists $args{agent} ? $args{agent} : $class->_agent );
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
129 delete $self->{proxy};
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;
140 delete $self->{http_proxy};
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;
151 delete $self->{https_proxy};
155 # Split no_proxy to array reference if not provided as such
156 unless ( ref $self->{no_proxy} eq 'ARRAY' ) {
158 (defined $self->{no_proxy}) ? [ split /\s*,\s*/, $self->{no_proxy} ] : [];
164 # =method get|head|put|post|delete
166 # $response = $http->get($url);
167 # $response = $http->get($url, \%options);
168 # $response = $http->head($url);
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.
174 # The C<success> field of the response will be true if the status code is 2XX.
178 for my $sub_name ( qw/get head put post delete/ ) {
179 my $req_method = uc $sub_name;
181 eval <<"HERE"; ## no critic
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 || {});
193 # $response = $http->post_form($url, $form_data);
194 # $response = $http->post_form($url, $form_data, \%options);
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.
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.
207 # The C<success> field of the response will be true if the status code is 2XX.
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");
217 while ( my ($key, $value) = each %{$args->{headers} || {}} ) {
218 $headers->{lc $key} = $value;
220 delete $args->{headers};
222 return $self->request('POST', $url, {
224 content => $self->www_form_urlencode($data),
227 'content-type' => 'application/x-www-form-urlencoded'
235 # $response = $http->mirror($url, $file, \%options)
236 # if ( $response->{success} ) {
237 # print "$file is up to date\n";
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.
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).
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.
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);
263 my $tempfile = $file . int(rand(2**31));
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/);
269 $args->{data_callback} = sub { print {$fh} $_[0] };
270 my $response = $self->request('GET', $url, $args);
272 or Carp::croak(qq/Error: Caught error closing temporary file $tempfile: $!\n/);
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;
282 $response->{success} ||= $response->{status} eq '304';
289 # $response = $http->request($method, $url);
290 # $response = $http->request($method, $url, \%options);
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.
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:
300 # $http->request('GET', 'http://Aladdin:open sesame@example.com/');
302 # If the "user:password" stanza contains reserved characters, they must
303 # be percent-escaped:
305 # $http->request('GET', 'http://john%40example.com:password@example.com/');
307 # A hashref of options may be appended to modify the request.
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.
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)
323 # A code reference that will be called for each chunks of the response
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.
330 # If the C<content> option is the empty string, no C<content-type> or
331 # C<content-length> headers will be generated.
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.)
340 # The C<request> method returns a hashref containing the response. The hashref
341 # will have the following keys:
345 # Boolean indicating whether the operation returned a 2XX status code
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
351 # The HTTP status code of the response
353 # The response phrase returned by the server
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
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
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.
368 my %idempotent = map { $_ => 1 } qw/GET HEAD PUT DELETE OPTIONS TRACE/;
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
376 # RFC 2616 Section 8.1.4 mandates a single retry on broken socket
379 $response = eval { $self->_request($method, $url, $args) };
380 last unless $@ && $idempotent{$method}
381 && $@ =~ m{^(?:Socket closed|Unexpected end)};
385 # maybe we got a response hash thrown from somewhere deep
386 if ( ref $e eq 'HASH' && exists $e->{status} ) {
390 # otherwise, stringify it
396 reason => 'Internal Exception',
399 'content-type' => 'text/plain',
400 'content-length' => length $e,
407 # =method www_form_urlencode
409 # $params = $http->www_form_urlencode( $data );
410 # $response = $http->get("http://example.com/query?$params");
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.
421 sub 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");
428 my @params = ref $data eq 'HASH' ? %$data : @$data;
430 or Carp::croak("form data reference must have an even number of terms\n");
434 my ($key, $value) = splice(@params, 0, 2);
435 if ( ref $value eq 'ARRAY' ) {
436 unshift @params, map { $key => $_ } @$value;
439 push @terms, join("=", map { $self->_uri_escape($_) } $key, $value);
443 return join("&", (ref $data eq 'ARRAY') ? (@terms) : (sort @terms) );
446 #--------------------------------------------------------------------------#
448 #--------------------------------------------------------------------------#
456 my $class = ref($_[0]) || $_[0];
457 (my $default_agent = $class) =~ s{::}{-}g;
458 return $default_agent . "/" . ($class->VERSION || 0);
462 my ($self, $method, $url, $args) = @_;
464 my ($scheme, $host, $port, $path_query, $auth) = $self->_split_url($url);
470 host_port => ($port == $DefaultPort{$scheme} ? $host : "$host:$port"),
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};
480 unless ( $handle->can_reuse( $scheme, $host, $port ) ) {
485 $handle ||= $self->_open_handle( $request, $scheme, $host, $port );
487 $self->_prepare_headers_and_cb($request, $args, $url, $auth);
488 $handle->write_request($request);
491 do { $response = $handle->read_response_header }
492 until (substr($response->{status},0,1) ne '1');
494 $self->_update_cookie_jar( $url, $response ) if $self->{cookie_jar};
496 if ( my @redir_args = $self->_maybe_redirect($request, $response, $args) ) {
498 return $self->_request(@redir_args, $args);
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;
507 my $data_cb = $self->_prepare_data_cb($response, $args);
508 $known_message_length = $handle->read_body($data_cb, $response);
511 if ( $self->{keep_alive}
512 && $known_message_length
513 && $response->{protocol} eq 'HTTP/1.1'
514 && ($response->{headers}{connection} || '') ne 'close'
516 $self->{handle} = $handle;
522 $response->{success} = substr( $response->{status}, 0, 1 ) eq '2';
523 $response->{url} = $url;
528 my ($self, $request, $scheme, $host, $port) = @_;
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}
538 if ($self->{_has_proxy}{$scheme} && ! grep { $host =~ /\Q$_\E$/ } @{$self->{no_proxy}}) {
539 return $self->_proxy_connect( $request, $handle );
542 return $handle->connect($scheme, $host, $port);
547 my ($self, $request, $handle) = @_;
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}});
558 Carp::croak(qq{No http_proxy defined}) unless $self->{http_proxy};
559 @proxy_vars = $self->_split_proxy( http_proxy => $self->{http_proxy} );
562 my ($p_scheme, $p_host, $p_port, $p_auth) = @proxy_vars;
564 if ( length $p_auth && ! defined $request->{headers}{'proxy-authorization'} ) {
565 $self->_add_basic_auth_header( $request, 'proxy-authorization' => $p_auth );
568 $handle->connect($p_scheme, $p_host, $p_port);
570 if ($request->{scheme} eq 'https') {
571 $self->_create_proxy_tunnel( $request, $handle );
574 # non-tunneled proxy requires absolute URI
575 $request->{uri} = "$request->{scheme}://$request->{host_port}$request->{uri}";
582 my ($self, $type, $proxy) = @_;
584 my ($scheme, $host, $port, $path_query, $auth) = eval { $self->_split_url($proxy) };
587 defined($scheme) && length($scheme) && length($host) && length($port)
588 && $path_query eq '/'
590 Carp::croak(qq{$type URL must be in format http[s]://[auth@]<host>:<port>/\n});
593 return ($scheme, $host, $port, $auth);
596 sub _create_proxy_tunnel {
597 my ($self, $request, $handle) = @_;
599 $handle->_assert_ssl;
601 my $agent = exists($request->{headers}{'user-agent'})
602 ? $request->{headers}{'user-agent'} : $self->{agent};
604 my $connect_request = {
606 uri => $request->{host_port},
608 host => $request->{host_port},
609 'user-agent' => $agent,
613 if ( $request->{headers}{'proxy-authorization'} ) {
614 $connect_request->{headers}{'proxy-authorization'} =
615 delete $request->{headers}{'proxy-authorization'};
618 $handle->write_request($connect_request);
620 do { $response = $handle->read_response_header }
621 until (substr($response->{status},0,1) ne '1');
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') {
629 # tunnel established, so start SSL handshake
630 $handle->start_ssl( $request->{host} );
635 sub _prepare_headers_and_cb {
636 my ($self, $request, $args, $url, $auth) = @_;
638 for ($self->{default_headers}, $args->{headers}) {
640 while (my ($k, $v) = each %$_) {
641 $request->{headers}{lc $k} = $v;
644 $request->{headers}{'host'} = $request->{host_port};
645 $request->{headers}{'user-agent'} ||= $self->{agent};
646 $request->{headers}{'connection'} = "close"
647 unless $self->{keep_alive};
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};
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/);
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, '' };
669 $request->{trailer_cb} = $args->{trailer_callback}
670 if ref $args->{trailer_callback} eq 'CODE';
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;
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 );
687 sub _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, "");
695 sub _prepare_data_cb {
696 my ($self, $response, $args) = @_;
697 my $data_cb = $args->{data_callback};
698 $response->{content} = '';
700 if (!$data_cb || $response->{status} !~ /^2/) {
701 if (defined $self->{max_size}) {
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};
709 $data_cb = sub { $_[1]->{content} .= $_[0] };
715 sub _update_cookie_jar {
716 my ($self, $url, $response) = @_;
718 my $cookies = $response->{headers}->{'set-cookie'};
719 return unless defined $cookies;
721 my @cookies = ref $cookies ? @$cookies : $cookies;
723 $self->cookie_jar->add( $url, $_ ) for @cookies;
728 sub _validate_cookie_jar {
729 my ($class, $jar) = @_;
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);
740 sub _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}
748 my $location = ($headers->{location} =~ /^\//)
749 ? "$request->{scheme}://$request->{host_port}$headers->{location}"
750 : $headers->{location} ;
751 return (($status eq '303' ? 'GET' : $method), $location);
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/);
763 $scheme = lc $scheme;
764 $path_query = "/$path_query" unless $path_query =~ m<\A/>;
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;
779 $host =~ s/:([0-9]*)\z// && length $1
781 : ($scheme eq 'http' ? 80 : $scheme eq 'https' ? 443 : undef);
784 return ($scheme, $host, $port, $path_query, $auth);
787 # Date conversions adapted from HTTP::Date
788 my $DoW = "Sun|Mon|Tue|Wed|Thu|Fri|Sat";
789 my $MoY = "Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec";
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,
799 sub _parse_http_date {
800 my ($self, $str) = @_;
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);
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);
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);
813 my $t = @tl_parts ? Time::Local::timegm(@tl_parts) : -1;
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
821 my %escapes = map { chr($_) => sprintf("%%%02X", $_) } 0..255;
823 my $unsafe_char = qr/[^A-Za-z0-9\-\._~]/;
826 my ($self, $str) = @_;
827 if ( $] ge '5.008' ) {
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
835 $str =~ s/($unsafe_char)/$escapes{$1}/ge;
840 HTTP::Tiny::Handle; # hide from PAUSE/indexers
844 use Errno qw[EINTR EPIPE];
845 use IO::Socket qw[SOCK_STREAM];
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
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' :
855 sub BUFSIZE () { 32768 } ## no critic
857 my $Printable = sub {
862 s/([^\x20-\x7E])/sprintf('\\x%.2X', ord($1))/ge;
866 my $Token = qr/[\x21\x23-\x27\x2A\x2B\x2D\x2E\x30-\x39\x41-\x5A\x5E-\x7A\x7C\x7E]/;
869 my ($class, %args) = @_;
873 max_line_size => 16384,
874 max_header_lines => 64,
882 @_ == 4 || die(q/Usage: $handle->connect(scheme, host, port)/ . "\n");
883 my ($self, $scheme, $host, $port) = @_;
885 if ( $scheme eq 'https' ) {
888 elsif ( $scheme ne 'http' ) {
889 die(qq/Unsupported URL scheme '$scheme'\n/);
891 $self->{fh} = $SOCKET_CLASS->new(
894 $self->{local_address} ?
895 ( LocalAddr => $self->{local_address} ) : (),
898 Timeout => $self->{timeout},
899 KeepAlive => !!$self->{keep_alive}
900 ) or die(qq/Could not connect to '$host:$port': $@\n/);
903 or die(qq/Could not binmode() socket: '$!'\n/);
905 $self->start_ssl($host) if $scheme eq 'https';
907 $self->{scheme} = $scheme;
908 $self->{host} = $host;
909 $self->{port} = $port;
915 my ($self, $host) = @_;
917 # As this might be used via CONNECT after an SSL session
918 # to a proxy, we shut down any existing SSL before attempting
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/);
927 my $ssl_args = $self->_ssl_args($host);
928 IO::Socket::SSL->start_SSL(
931 SSL_create_ctx_callback => sub {
933 Net::SSLeay::CTX_set_mode($ctx, Net::SSLeay::MODE_AUTO_RETRY());
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/);
944 @_ == 1 || die(q/Usage: $handle->close()/ . "\n");
946 CORE::close($self->{fh})
947 or die(qq/Could not close socket: '$!'\n/);
951 @_ == 2 || die(q/Usage: $handle->write(buf)/ . "\n");
952 my ($self, $buf) = @_;
954 if ( $] ge '5.008' ) {
955 utf8::downgrade($buf, 1)
956 or die(qq/Wide character in write()\n/);
959 my $len = length $buf;
962 local $SIG{PIPE} = 'IGNORE';
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);
971 last unless $len > 0;
973 elsif ($! == EPIPE) {
974 die(qq/Socket closed by remote server: $!\n/);
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 /);
982 die(qq/Could not write to socket: '$!'\n/);
991 @_ == 2 || @_ == 3 || die(q/Usage: $handle->read(len [, allow_partial])/ . "\n");
992 my ($self, $len, $allow_partial) = @_;
995 my $got = length $self->{rbuf};
998 my $take = ($got < $len) ? $got : $len;
999 $buf = substr($self->{rbuf}, 0, $take, '');
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);
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 /);
1017 die(qq/Could not read from socket: '$!'\n/);
1021 if ($len && !$allow_partial) {
1022 die(qq/Unexpected end of stream\n/);
1028 @_ == 1 || die(q/Usage: $handle->readline()/ . "\n");
1032 if ($self->{rbuf} =~ s/\A ([^\x0D\x0A]* \x0D?\x0A)//x) {
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/);
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});
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 /);
1050 die(qq/Could not read from socket: '$!'\n/);
1054 die(qq/Unexpected end of stream while looking for line\n/);
1057 sub read_header_lines {
1058 @_ == 1 || @_ == 2 || die(q/Usage: $handle->read_header_lines([headers])/ . "\n");
1059 my ($self, $headers) = @_;
1065 my $line = $self->readline;
1067 if (++$lines >= $self->{max_header_lines}) {
1068 die(qq/Header lines exceeds maximum number allowed of $self->{max_header_lines}\n/);
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";
1080 $val = \($headers->{$field_name} = $2);
1083 elsif ($line =~ /\A [\x09\x20]+ ([^\x0D\x0A]*)/x) {
1085 or die(qq/Unexpected header continuation line\n/);
1086 next unless length $1;
1087 $$val .= ' ' if length $$val;
1090 elsif ($line =~ /\A \x0D?\x0A \z/x) {
1094 die(q/Malformed header line: / . $Printable->($line) . "\n");
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};
1109 'content-md5' => 'Content-MD5',
1112 'www-authenticate' => 'WWW-Authenticate',
1113 'x-xss-protection' => 'X-XSS-Protection',
1116 # to avoid multiple small writes and hence nagle, you can pass the method line or anything else to
1118 sub 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) = @_;
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};
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;
1134 for (ref $v eq 'ARRAY' ? @$v : $v) {
1136 or die(qq/Invalid HTTP header field value ($field_name): / . $Printable->($_). "\n");
1137 $buf .= "$field_name: $_\x0D\x0A";
1141 return $self->write($buf);
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
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 ) ;
1153 ? $self->read_chunked_body($cb, $response)
1154 : $self->read_content_body($cb, $response);
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);
1164 return $self->write_chunked_body($request);
1168 sub 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'};
1173 if ( defined $content_length ) {
1174 my $len = $content_length;
1176 my $read = ($len > BUFSIZE) ? BUFSIZE : $len;
1177 $cb->($self->read($read, 0), $response);
1180 return length($self->{rbuf}) == 0;
1184 $cb->($chunk, $response) while length( $chunk = $self->read(BUFSIZE, 1) );
1189 sub write_content_body {
1190 @_ == 2 || die(q/Usage: $handle->write_content_body(request)/ . "\n");
1191 my ($self, $request) = @_;
1193 my ($len, $content_length) = (0, $request->{headers}{'content-length'});
1195 my $data = $request->{cb}->();
1197 defined $data && length $data
1200 if ( $] ge '5.008' ) {
1201 utf8::downgrade($data, 1)
1202 or die(qq/Wide character in write_content()\n/);
1205 $len += $self->write($data);
1208 $len == $content_length
1209 or die(qq/Content-Length missmatch (got: $len expected: $content_length)\n/);
1214 sub read_chunked_body {
1215 @_ == 3 || die(q/Usage: $handle->read_chunked_body(callback, $response)/ . "\n");
1216 my ($self, $cb, $response) = @_;
1219 my $head = $self->readline;
1221 $head =~ /\A ([A-Fa-f0-9]+)/x
1222 or die(q/Malformed chunk head: / . $Printable->($head) . "\n");
1227 $self->read_content_body($cb, $response, $len);
1229 $self->read(2) eq "\x0D\x0A"
1230 or die(qq/Malformed chunk: missing CRLF after chunk data\n/);
1232 $self->read_header_lines($response->{headers});
1236 sub write_chunked_body {
1237 @_ == 2 || die(q/Usage: $handle->write_chunked_body(request)/ . "\n");
1238 my ($self, $request) = @_;
1242 my $data = $request->{cb}->();
1244 defined $data && length $data
1247 if ( $] ge '5.008' ) {
1248 utf8::downgrade($data, 1)
1249 or die(qq/Wide character in write_chunked_body()\n/);
1252 $len += length $data;
1254 my $chunk = sprintf '%X', length $data;
1255 $chunk .= "\x0D\x0A";
1257 $chunk .= "\x0D\x0A";
1259 $self->write($chunk);
1261 $self->write("0\x0D\x0A");
1262 $self->write_header_lines($request->{trailer_cb}->())
1263 if ref $request->{trailer_cb} eq 'CODE';
1267 sub read_response_header {
1268 @_ == 1 || die(q/Usage: $handle->read_response_header()/ . "\n");
1271 my $line = $self->readline;
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");
1276 my ($protocol, $version, $status, $reason) = ($1, $2, $3, $4);
1278 die (qq/Unsupported HTTP protocol: $protocol\n/)
1279 unless $version =~ /0*1\.0*[01]/;
1284 headers => $self->read_header_lines,
1285 protocol => $protocol,
1289 sub write_request_header {
1290 @_ == 4 || die(q/Usage: $handle->write_request_header(method, request_uri, headers)/ . "\n");
1291 my ($self, $method, $request_uri, $headers) = @_;
1293 return $self->write_header_lines($headers, "$method $request_uri HTTP/1.1\x0D\x0A");
1297 my ($self, $type, $timeout) = @_;
1298 $timeout = $self->{timeout}
1299 unless defined $timeout && $timeout >= 0;
1301 my $fd = fileno $self->{fh};
1302 defined $fd && $fd >= 0
1303 or die(qq/select(2): 'Bad file descriptor'\n/);
1306 my $pending = $timeout;
1309 vec(my $fdset = '', $fd, 1) = 1;
1312 $nfound = ($type eq 'read')
1313 ? select($fdset, undef, undef, $pending)
1314 : select(undef, $fdset, undef, $pending) ;
1315 if ($nfound == -1) {
1317 or die(qq/select(2): '$!'\n/);
1318 redo if !$timeout || ($pending = $timeout - (time - $initial)) > 0;
1328 @_ == 1 || @_ == 2 || die(q/Usage: $handle->can_read([timeout])/ . "\n");
1330 if ( ref($self->{fh}) eq 'IO::Socket::SSL' ) {
1331 return 1 if $self->{fh}->pending;
1333 return $self->_do_timeout('read', @_)
1337 @_ == 1 || @_ == 2 || die(q/Usage: $handle->can_write([timeout])/ . "\n");
1339 return $self->_do_timeout('write', @_)
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)};
1352 my ($self,$scheme,$host,$port) = @_;
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) }
1363 # Try to find a CA bundle to validate the SSL cert,
1364 # prefer Mozilla::CA or fallback to a system file
1368 return $self->{SSL_options}->{SSL_ca_file}
1369 if $self->{SSL_options}->{SSL_ca_file} and -e $self->{SSL_options}->{SSL_ca_file};
1371 return Mozilla::CA::SSL_ca_file()
1372 if eval { require Mozilla::CA };
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
1380 return $ca_bundle if -e $ca_bundle;
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/;
1388 my ($self, $host) = @_;
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
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;
1405 $ssl_args{SSL_verifycn_scheme} = 'none'; # disable CN validation
1406 $ssl_args{SSL_verify_mode} = 0x00; # disable cert validation
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_/;
1427 HTTP::Tiny - A small, simple, correct HTTP/1.1 client
1437 my $response = HTTP::Tiny->new->get('http://example.com/');
1439 die "Failed!\n" unless $response->{success};
1441 print "$response->{status} $response->{reason}\n";
1443 while (my ($k, $v) = each %{$response->{headers}}) {
1444 for (ref $v eq 'ARRAY' ? @$v : $v) {
1449 print $response->{content} if length $response->{content};
1453 This is a very simple HTTP/1.1 client, designed for doing simple
1454 requests without the overhead of a large framework like L<LWP::UserAgent>.
1456 It is more correct and more complete than L<HTTP::Lite>. It supports
1457 proxies and redirection. It also correctly resumes after EINTR.
1459 If L<IO::Socket::IP> 0.25 or later is installed, HTTP::Tiny will use it instead
1460 of L<IO::Socket::INET> for transparent support for both IPv4 and IPv6.
1462 Cookie support requires L<HTTP::CookieJar> or an equivalent class.
1468 $http = HTTP::Tiny->new( %attributes );
1470 This constructor returns a new HTTP::Tiny object. Valid attributes include:
1478 A user-agent string (defaults to 'HTTP-Tiny/$VERSION'). If C<agent> ends in a space character, the default user-agent string is appended.
1484 An instance of L<HTTP::CookieJar> or equivalent class that supports the C<add> and C<cookie_header> methods
1490 A hashref of default headers to apply to requests
1496 The local IP address to bind to
1502 Whether to reuse the last connection (if for the same scheme, host and port) (defaults to 1)
1508 Maximum number of redirects allowed (defaults to 5)
1514 Maximum response size (only when not using a data callback). If defined, responses larger than this will return an exception.
1520 URL of a proxy server to use for HTTP connections (default is C<$ENV{http_proxy}> if set)
1526 URL of a proxy server to use for HTTPS connections (default is C<$ENV{https_proxy}> if set)
1532 URL of a generic proxy server for both HTTP and HTTPS connections (default is C<$ENV{all_proxy}> if set)
1538 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}>)
1544 Request timeout in seconds (default is 60)
1550 A boolean that indicates whether to validate the SSL certificate of an C<https>
1551 connection (default is false)
1557 A hashref of C<SSL_*> options to pass through to L<IO::Socket::SSL>
1561 Exceptions from C<max_size>, C<timeout> or other errors will result in a
1562 pseudo-HTTP status code of 599 and a reason of "Internal Exception". The
1563 content field in the response will contain the text of the exception.
1565 The C<keep_alive> parameter enables a persistent connection, but only to a
1566 single destination scheme, host and port. Also, if any connection-relevant
1567 attributes are modified, a persistent connection will be dropped. If you want
1568 persistent connections across multiple destinations, use multiple HTTP::Tiny
1571 See L</SSL SUPPORT> for more on the C<verify_SSL> and C<SSL_options> attributes.
1573 =head2 get|head|put|post|delete
1575 $response = $http->get($url);
1576 $response = $http->get($url, \%options);
1577 $response = $http->head($url);
1579 These methods are shorthand for calling C<request()> for the given method. The
1580 URL must have unsafe characters escaped and international domain names encoded.
1581 See C<request()> for valid options and a description of the response.
1583 The C<success> field of the response will be true if the status code is 2XX.
1587 $response = $http->post_form($url, $form_data);
1588 $response = $http->post_form($url, $form_data, \%options);
1590 This method executes a C<POST> request and sends the key/value pairs from a
1591 form data hash or array reference to the given URL with a C<content-type> of
1592 C<application/x-www-form-urlencoded>. If data is provided as an array
1593 reference, the order is preserved; if provided as a hash reference, the terms
1594 are sorted on key and value for consistency. See documentation for the
1595 C<www_form_urlencode> method for details on the encoding.
1597 The URL must have unsafe characters escaped and international domain names
1598 encoded. See C<request()> for valid options and a description of the response.
1599 Any C<content-type> header or content in the options hashref will be ignored.
1601 The C<success> field of the response will be true if the status code is 2XX.
1605 $response = $http->mirror($url, $file, \%options)
1606 if ( $response->{success} ) {
1607 print "$file is up to date\n";
1610 Executes a C<GET> request for the URL and saves the response body to the file
1611 name provided. The URL must have unsafe characters escaped and international
1612 domain names encoded. If the file already exists, the request will include an
1613 C<If-Modified-Since> header with the modification timestamp of the file. You
1614 may specify a different C<If-Modified-Since> header yourself in the C<<
1615 $options->{headers} >> hash.
1617 The C<success> field of the response will be true if the status code is 2XX
1618 or if the status code is 304 (unmodified).
1620 If the file was modified and the server response includes a properly
1621 formatted C<Last-Modified> header, the file modification time will
1622 be updated accordingly.
1626 $response = $http->request($method, $url);
1627 $response = $http->request($method, $url, \%options);
1629 Executes 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
1631 international domain names encoded.
1633 If the URL includes a "user:password" stanza, they will be used for Basic-style
1634 authorization headers. (Authorization headers will not be included in a
1635 redirected request.) For example:
1637 $http->request('GET', 'http://Aladdin:open sesame@example.com/');
1639 If the "user:password" stanza contains reserved characters, they must
1642 $http->request('GET', 'http://john%40example.com:password@example.com/');
1644 A hashref of options may be appended to modify the request.
1654 A hashref containing headers to include with the request. If the value for
1655 a header is an array reference, the header will be output multiple times with
1656 each value in the array. These headers over-write any default headers.
1662 A scalar to include as the body of the request OR a code reference
1663 that will be called iteratively to produce the body of the request
1669 A code reference that will be called if it exists to provide a hashref
1670 of trailing headers (only used with chunked transfer-encoding)
1676 A code reference that will be called for each chunks of the response
1681 If the C<content> option is a code reference, it will be called iteratively
1682 to provide the content body of the request. It should return the empty
1683 string or undef when the iterator is exhausted.
1685 If the C<content> option is the empty string, no C<content-type> or
1686 C<content-length> headers will be generated.
1688 If the C<data_callback> option is provided, it will be called iteratively until
1689 the entire response body is received. The first argument will be a string
1690 containing a chunk of the response body, the second argument will be the
1691 in-progress response hash reference, as described below. (This allows
1692 customizing the action of the callback based on the C<status> or C<headers>
1693 received prior to the content body.)
1695 The C<request> method returns a hashref containing the response. The hashref
1696 will have the following keys:
1704 Boolean indicating whether the operation returned a 2XX status code
1710 URL that provided the response. This is the URL of the request unless
1711 there were redirections, in which case it is the last URL queried
1712 in a redirection chain
1718 The HTTP status code of the response
1724 The response phrase returned by the server
1730 The body of the response. If the response does not have any content
1731 or if a data callback is provided to consume the response body,
1732 this will be the empty string
1738 A hashref of header fields. All header field names will be normalized
1739 to be lower case. If a header is repeated, the value will be an arrayref;
1740 it will otherwise be a scalar string containing the value
1744 On an exception during the execution of the request, the C<status> field will
1745 contain 599, and the C<content> field will contain the text of the exception.
1747 =head2 www_form_urlencode
1749 $params = $http->www_form_urlencode( $data );
1750 $response = $http->get("http://example.com/query?$params");
1752 This method converts the key/value pairs from a data hash or array reference
1753 into a C<x-www-form-urlencoded> string. The keys and values from the data
1754 reference will be UTF-8 encoded and escaped per RFC 3986. If a value is an
1755 array reference, the key will be repeated with each of the values of the array
1756 reference. If data is provided as a hash reference, the key/value pairs in the
1757 resulting string will be sorted by key and value for consistent ordering.
1759 =for Pod::Coverage SSL_options
1776 Direct C<https> connections are supported only if L<IO::Socket::SSL> 1.56 or
1777 greater and L<Net::SSLeay> 1.49 or greater are installed. An exception will be
1778 thrown if a new enough versions of these modules not installed or if the SSL
1779 encryption fails. An C<https> connection may be made via an C<http> proxy that
1780 supports the CONNECT command (i.e. RFC 2817). You may not proxy C<https> via
1781 a proxy that itself requires C<https> to communicate.
1783 SSL provides two distinct capabilities:
1789 Encrypted communication channel
1793 Verification of server identity
1797 B<By default, HTTP::Tiny does not verify server identity>.
1799 Server identity verification is controversial and potentially tricky because it
1800 depends on a (usually paid) third-party Certificate Authority (CA) trust model
1801 to validate a certificate as legitimate. This discriminates against servers
1802 with self-signed certificates or certificates signed by free, community-driven
1803 CA's such as L<CAcert.org|http://cacert.org>.
1805 By default, HTTP::Tiny does not make any assumptions about your trust model,
1806 threat level or risk tolerance. It just aims to give you an encrypted channel
1809 Setting the C<verify_SSL> attribute to a true value will make HTTP::Tiny verify
1810 that an SSL connection has a valid SSL certificate corresponding to the host
1811 name of the connection and that the SSL certificate has been verified by a CA.
1812 Assuming you trust the CA, this will protect against a L<man-in-the-middle
1813 attack|http://en.wikipedia.org/wiki/Man-in-the-middle_attack>. If you are
1814 concerned about security, you should enable this option.
1816 Certificate verification requires a file containing trusted CA certificates.
1817 If the L<Mozilla::CA> module is installed, HTTP::Tiny will use the CA file
1818 included with it as a source of trusted CA's. (This means you trust Mozilla,
1819 the author of Mozilla::CA, the CPAN mirror where you got Mozilla::CA, the
1820 toolchain used to install it, and your operating system security, right?)
1822 If that module is not available, then HTTP::Tiny will search several
1823 system-specific default locations for a CA certificate file:
1829 /etc/ssl/certs/ca-certificates.crt
1833 /etc/pki/tls/certs/ca-bundle.crt
1837 /etc/ssl/ca-bundle.pem
1841 An exception will be raised if C<verify_SSL> is true and no CA certificate file
1844 If you desire complete control over SSL connections, the C<SSL_options> attribute
1845 lets you provide a hash reference that will be passed through to
1846 C<IO::Socket::SSL::start_SSL()>, overriding any options set by HTTP::Tiny. For
1847 example, to provide your own trusted CA file:
1850 SSL_ca_file => $file_path,
1853 The C<SSL_options> attribute could also be used for such things as providing a
1854 client certificate for authentication to a server or controlling the choice of
1855 cipher used for the SSL connection. See L<IO::Socket::SSL> documentation for
1858 =head1 PROXY SUPPORT
1860 HTTP::Tiny can proxy both C<http> and C<https> requests. Only Basic proxy
1861 authorization is supported and it must be provided as part of the proxy URL:
1862 C<http://user:pass@proxy.example.com/>.
1864 HTTP::Tiny supports the following proxy environment variables:
1874 https_proxy or HTTPS_PROXY
1878 all_proxy or ALL_PROXY
1882 Tunnelling C<https> over an C<http> proxy using the CONNECT method is
1883 supported. If your proxy uses C<https> itself, you can not tunnel C<https>
1886 Be warned that proxying an C<https> connection opens you to the risk of a
1887 man-in-the-middle attack by the proxy server.
1889 The C<no_proxy> environment variable is supported in the format of a
1890 comma-separated list of domain extensions proxy should not be used for.
1892 Proxy arguments passed to C<new> will override their corresponding
1893 environment variables.
1897 HTTP::Tiny is I<conditionally compliant> with the
1898 L<HTTP/1.1 specification|http://www.w3.org/Protocols/rfc2616/rfc2616.html>.
1899 It attempts to meet all "MUST" requirements of the specification, but does not
1900 implement all "SHOULD" requirements.
1902 Some particular limitations of note include:
1908 HTTP::Tiny focuses on correct transport. Users are responsible for ensuring
1909 that user-defined headers and content are compliant with the HTTP/1.1
1914 Users must ensure that URLs are properly escaped for unsafe characters and that
1915 international domain names are properly encoded to ASCII. See L<URI::Escape>,
1916 L<URI::_punycode> and L<Net::IDN::Encode>.
1920 Redirection is very strict against the specification. Redirection is only
1921 automatic 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
1923 mandated by the specification. There is no automatic support for status 305
1924 ("Use proxy") redirections.
1928 There is no provision for delaying a request body using an C<Expect> header.
1929 Unexpected C<1XX> responses are silently ignored as per the specification.
1933 Only 'chunked' C<Transfer-Encoding> is supported.
1937 There is no support for a Request-URI of '*' for the 'OPTIONS' request.
1941 Despite the limitations listed above, HTTP::Tiny is considered
1942 feature-complete. New feature requests should be directed to
1951 L<HTTP::Tiny::UA> - Higher level UA features for HTTP::Tiny
1955 L<HTTP::Thin> - HTTP::Tiny wrapper with L<HTTP::Request>/L<HTTP::Response> compatibility
1959 L<HTTP::Tiny::Mech> - Wrap L<WWW::Mechanize> instance in HTTP::Tiny compatible interface
1963 L<IO::Socket::IP> - Required for IPv6 support
1967 L<IO::Socket::SSL> - Required for SSL support
1971 L<LWP::UserAgent> - If HTTP::Tiny isn't enough for you, this is the "standard" way to do things
1975 L<Mozilla::CA> - Required if you want to validate SSL certificates
1979 L<Net::SSLeay> - Required for SSL support
1983 =for :stopwords cpan testmatrix url annocpan anno bugtracker rt cpants kwalitee diff irc mailto metadata placeholders metacpan
1987 =head2 Bugs / Feature Requests
1989 Please report any bugs or feature requests through the issue tracker
1990 at L<https://github.com/chansen/p5-http-tiny/issues>.
1991 You will be notified automatically of any progress on your issue.
1995 This is open source software. The code repository is available for
1996 public review and contribution under the terms of the license.
1998 L<https://github.com/chansen/p5-http-tiny>
2000 git clone https://github.com/chansen/p5-http-tiny.git
2008 Christian Hansen <chansen@cpan.org>
2012 David Golden <dagolden@cpan.org>
2022 Alan Gardner <gardner@pythian.com>
2026 Alessandro Ghedini <al3xbio@gmail.com>
2030 Brad Gilbert <bgills@cpan.org>
2034 Chris Nehren <apeiron@cpan.org>
2038 Chris Weyl <cweyl@alumni.drew.edu>
2042 Claes Jakobsson <claes@surfar.nu>
2046 Clinton Gormley <clint@traveljury.com>
2050 Craig Berry <cberry@cpan.org>
2054 David Mitchell <davem@iabyn.com>
2058 Edward Zborowski <ed@rubensteintech.com>
2062 Jess Robinson <castaway@desert-island.me.uk>
2066 Lukas Eklund <leklund@gmail.com>
2070 Martin J. Evans <mjegh@ntlworld.com>
2074 Martin-Louis Bright <mlbright@gmail.com>
2078 Mike Doherty <doherty@cpan.org>
2082 Petr Písař <ppisar@redhat.com>
2086 Serguei Trouchelle <stro@cpan.org>
2090 Syohei YOSHIDA <syohex@gmail.com>
2094 Tony Cook <tony@develop-help.com>
2098 =head1 COPYRIGHT AND LICENSE
2100 This software is copyright (c) 2014 by Christian Hansen.
2102 This is free software; you can redistribute it and/or modify it under
2103 the same terms as the Perl 5 programming language system itself.