1package Hijk; 2use strict; 3use warnings; 4use Time::HiRes; 5use POSIX qw(:errno_h); 6use Socket qw(PF_INET SOCK_STREAM pack_sockaddr_in $CRLF SOL_SOCKET SO_ERROR); 7use Fcntl qw(F_GETFL F_SETFL O_NONBLOCK); 8 9our $VERSION = "0.28"; 10 11sub Hijk::Error::CONNECT_TIMEOUT () { 1 << 0 } # 1 12sub Hijk::Error::READ_TIMEOUT () { 1 << 1 } # 2 13sub Hijk::Error::TIMEOUT () { Hijk::Error::READ_TIMEOUT | Hijk::Error::CONNECT_TIMEOUT } # 3 14sub Hijk::Error::CANNOT_RESOLVE () { 1 << 2 } # 4 15sub Hijk::Error::REQUEST_SELECT_ERROR () { 1 << 3 } # 8 16sub Hijk::Error::REQUEST_WRITE_ERROR () { 1 << 4 } # 16 17sub Hijk::Error::REQUEST_ERROR () { Hijk::Error::REQUEST_SELECT_ERROR | Hijk::Error::REQUEST_WRITE_ERROR } # 24 18sub Hijk::Error::RESPONSE_READ_ERROR () { 1 << 5 } # 32 19sub Hijk::Error::RESPONSE_BAD_READ_VALUE () { 1 << 6 } # 64 20sub Hijk::Error::RESPONSE_ERROR () { Hijk::Error::RESPONSE_READ_ERROR | Hijk::Error::RESPONSE_BAD_READ_VALUE } # 96 21 22sub _read_http_message { 23 my ($fd, $read_length, $read_timeout, $parse_chunked, $head_as_array, $method) = @_; 24 $read_timeout = undef if defined($read_timeout) && $read_timeout <= 0; 25 26 my ($body,$buf,$decapitated,$nbytes,$proto); 27 my $status_code = 0; 28 my $header = $head_as_array ? [] : {}; 29 my $no_content_len = 0; 30 my $head = ""; 31 my $method_has_no_content = do { no warnings qw(uninitialized); $method eq "HEAD" }; 32 my $close_connection; 33 vec(my $rin = '', $fd, 1) = 1; 34 do { 35 return ($close_connection,undef,0,undef,undef, Hijk::Error::READ_TIMEOUT) 36 if ((_select($rin, undef, undef, $read_timeout) != 1) || (defined($read_timeout) && $read_timeout <= 0)); 37 38 my $nbytes = POSIX::read($fd, $buf, $read_length); 39 return ($close_connection, $proto, $status_code, $header, $body) 40 if $no_content_len && $decapitated && (!defined($nbytes) || $nbytes == 0); 41 if (!defined($nbytes)) { 42 next if ($! == EWOULDBLOCK || $! == EAGAIN || $! == EINTR); 43 return ( 44 $close_connection, undef, 0, undef, undef, 45 Hijk::Error::RESPONSE_READ_ERROR, 46 "Failed to read http " . ($decapitated ? "body": "head") . " from socket", 47 $!+0, 48 "$!", 49 ); 50 } 51 52 if ($nbytes == 0) { 53 return ( 54 $close_connection, undef, 0, undef, undef, 55 Hijk::Error::RESPONSE_BAD_READ_VALUE, 56 "Wasn't expecting a 0 byte response for http " . ($decapitated ? "body": "head" ) . ". This shouldn't happen", 57 ); 58 } 59 60 if ($decapitated) { 61 $body .= $buf; 62 if (!$no_content_len) { 63 $read_length -= $nbytes; 64 } 65 } 66 else { 67 $head .= $buf; 68 my $neck_pos = index($head, "${CRLF}${CRLF}"); 69 if ($neck_pos > 0) { 70 $decapitated = 1; 71 $body = substr($head, $neck_pos+4); 72 $head = substr($head, 0, $neck_pos); 73 $proto = substr($head, 0, 8); 74 $status_code = substr($head, 9, 3); 75 $method_has_no_content = 1 if $status_code == 204; # 204 NO CONTENT, see http://tools.ietf.org/html/rfc2616#page-60 76 substr($head, 0, index($head, $CRLF) + 2, ""); # 2 = length($CRLF) 77 78 my ($doing_chunked, $content_length, $trailer_mode, $trailer_value_is_true); 79 for (split /${CRLF}/o, $head) { 80 my ($key, $value) = split /: /, $_, 2; 81 my $key_lc = lc($key); 82 83 # Figure this out now so we don't need to scan the 84 # list later under $head_as_array, and just for 85 # simplicity and to avoid duplicating code later 86 # when !$head_as_array. 87 if ($key_lc eq 'transfer-encoding' and $value eq 'chunked') { 88 $doing_chunked = 1; 89 } elsif ( ($key_lc eq 'content-length') || (lc($key) eq 'content-length') ) { 90 $content_length = $value; 91 } elsif ($key_lc eq 'connection' and $value eq 'close') { 92 $close_connection = 1; 93 } elsif ($key_lc eq 'trailer' and $value) { 94 $trailer_value_is_true = 1; 95 } 96 97 if ($head_as_array) { 98 push @$header => $key, $value; 99 } else { 100 $header->{$key} = $value; 101 } 102 } 103 104 # We're processing the headers as a stream, and we 105 # only want to turn on $trailer_mode if 106 # Transfer-Encoding=chunked && Trailer=TRUE. However I 107 # don't think there's any guarantee that 108 # Transfer-Encoding comes before Trailer, so we're 109 # effectively doing a second-pass here. 110 if ($doing_chunked and $trailer_value_is_true) { 111 $trailer_mode = 1; 112 } 113 114 if ($doing_chunked) { 115 die "PANIC: The experimental Hijk support for chunked transfer encoding needs to be explicitly enabled with parse_chunked => 1" 116 unless $parse_chunked; 117 118 # if there is chunked encoding we have to ignore content length even if we have it 119 return ( 120 $close_connection, $proto, $status_code, $header, 121 _read_chunked_body( 122 $body, $fd, $read_length, $read_timeout, 123 $head_as_array 124 ? $trailer_mode 125 : ($header->{Trailer} ? 1 : 0), 126 ), 127 ); 128 } 129 130 if (defined $content_length) { 131 if ($content_length == 0) { 132 $read_length = 0; 133 } else { 134 $read_length = $content_length - length($body); 135 } 136 } else { 137 $read_length = 10204; 138 $no_content_len = 1; 139 } 140 } 141 } 142 } while( !$decapitated || (!$method_has_no_content && ($read_length > 0 || $no_content_len)) ); 143 return ($close_connection, $proto, $status_code, $header, $body); 144} 145 146sub _read_chunked_body { 147 my ($buf,$fd,$read_length,$read_timeout,$true_trailer_header) = @_; 148 my $chunk_size = 0; 149 my $body = ""; 150 my $trailer_mode = 0; 151 my $wait_for_last_clrf = 0; 152 vec(my $rin = '', $fd, 1) = 1; 153 while(1) { 154 # just read a 10k block and process it until it is consumed 155 if (length($buf) < 3 || length($buf) < $chunk_size || $wait_for_last_clrf > 0) { 156 return (undef, Hijk::Error::READ_TIMEOUT) 157 if ((_select($rin, undef, undef, $read_timeout) != 1) || (defined($read_timeout) && $read_timeout <= 0)); 158 my $current_buf = ""; 159 my $nbytes = POSIX::read($fd, $current_buf, $read_length); 160 if (!defined($nbytes)) { 161 next if ($! == EWOULDBLOCK || $! == EAGAIN || $! == EINTR); 162 return ( 163 undef, 164 Hijk::Error::RESPONSE_READ_ERROR, 165 "Failed to chunked http body from socket", 166 $!+0, 167 "$!", 168 ); 169 } 170 171 if ($nbytes == 0) { 172 return ( 173 undef, 174 Hijk::Error::RESPONSE_BAD_READ_VALUE, 175 "Wasn't expecting a 0 byte response for chunked http body. This shouldn't happen, buf:<$buf>, current_buf:<$current_buf>", 176 ); 177 } 178 179 $buf .= $current_buf; 180 } 181 182 if ($wait_for_last_clrf > 0) { 183 $wait_for_last_clrf -= length($buf); 184 return $body if ($wait_for_last_clrf <= 0); 185 } 186 187 if ($trailer_mode) { 188 # http://tools.ietf.org/html/rfc2616#section-14.40 189 # http://tools.ietf.org/html/rfc2616#section-3.6.1 190 # A server using chunked transfer-coding in a response MUST NOT use the 191 # trailer for any header fields unless at least one of the following is 192 # true: 193 194 # a)the request included a TE header field that indicates "trailers" is 195 # acceptable in the transfer-coding of the response, as described in 196 # section 14.39; or, 197 198 # b)the server is the origin server for the response, the trailer 199 # fields consist entirely of optional metadata, and the recipient 200 # could use the message (in a manner acceptable to the origin server) 201 # without receiving this metadata. In other words, the origin server 202 # is willing to accept the possibility that the trailer fields might 203 # be silently discarded along the path to the client. 204 205 # in case of trailer mode, we just read everything until the next CRLFCRLF 206 my $neck_pos = index($buf, "${CRLF}${CRLF}"); 207 if ($neck_pos > 0) { 208 return $body; 209 } 210 } else { 211 if ($chunk_size > 0 && length($buf) >= $chunk_size) { 212 $body .= substr($buf, 0, $chunk_size - 2); # our chunk size includes the following CRLF 213 $buf = substr($buf, $chunk_size); 214 $chunk_size = 0; 215 } else { 216 my $neck_pos = index($buf, ${CRLF}); 217 if ($neck_pos > 0) { 218 $chunk_size = hex(substr($buf, 0, $neck_pos)); 219 if ($chunk_size == 0) { 220 if ($true_trailer_header) { 221 $trailer_mode = 1; 222 } else { 223 $buf = substr($buf, $neck_pos + 2); 224 # in case we are missing the ending CLRF, we have to wait for it 225 # otherwise it is left int he socket 226 if (length($buf) < 2) { 227 $wait_for_last_clrf = 2 - length($buf); 228 } else { 229 return $body; 230 } 231 } 232 } else { 233 $chunk_size += 2; # include the following CRLF 234 $buf = substr($buf, $neck_pos + 2); 235 } 236 } elsif($neck_pos == 0) { 237 return ( 238 undef, 239 Hijk::Error::RESPONSE_BAD_READ_VALUE, 240 "Wasn't expecting CLRF without chunk size. This shouldn't happen, buf:<$buf>", 241 ); 242 } 243 } 244 } 245 } 246} 247 248sub _construct_socket { 249 my ($host, $port, $connect_timeout) = @_; 250 251 # If we can't find the IP address there'll be no point in even 252 # setting up a socket. 253 my $addr; 254 { 255 my $inet_aton = gethostbyname($host); 256 return (undef, {error => Hijk::Error::CANNOT_RESOLVE}) unless defined $inet_aton; 257 $addr = pack_sockaddr_in($port, $inet_aton); 258 } 259 260 my $tcp_proto = getprotobyname("tcp"); 261 my $soc; 262 socket($soc, PF_INET, SOCK_STREAM, $tcp_proto) || die "Failed to construct TCP socket: $!"; 263 my $flags = fcntl($soc, F_GETFL, 0) or die "Failed to set fcntl F_GETFL flag: $!"; 264 fcntl($soc, F_SETFL, $flags | O_NONBLOCK) or die "Failed to set fcntl O_NONBLOCK flag: $!"; 265 266 if (!connect($soc, $addr) && $! != EINPROGRESS) { 267 die "Failed to connect $!"; 268 } 269 270 $connect_timeout = undef if defined($connect_timeout) && $connect_timeout <= 0; 271 vec(my $rout = '', fileno($soc), 1) = 1; 272 if (_select(undef, $rout, undef, $connect_timeout) != 1) { 273 if (defined($connect_timeout)) { 274 return (undef, {error => Hijk::Error::CONNECT_TIMEOUT}); 275 } else { 276 return ( 277 undef, 278 { 279 error => Hijk::Error::REQUEST_SELECT_ERROR, 280 error_message => "select() error on constructing the socket", 281 errno_number => $!+0, 282 errno_string => "$!", 283 }, 284 ); 285 } 286 } 287 288 if ($! = unpack("L", getsockopt($soc, SOL_SOCKET, SO_ERROR))) { 289 die $!; 290 } 291 292 return $soc; 293} 294 295sub _build_http_message { 296 my $args = $_[0]; 297 my $path_and_qs = ($args->{path} || "/") . ( defined($args->{query_string}) ? ("?".$args->{query_string}) : "" ); 298 return join( 299 $CRLF, 300 ($args->{method} || "GET")." $path_and_qs " . ($args->{protocol} || "HTTP/1.1"), 301 ($args->{no_default_host_header} 302 ? () 303 : ("Host: $args->{host}")), 304 defined($args->{body}) ? ("Content-Length: " . length($args->{body})) : (), 305 ($args->{head} and @{$args->{head}}) ? ( 306 map { 307 $args->{head}[2*$_] . ": " . $args->{head}[2*$_+1] 308 } 0..$#{$args->{head}}/2 309 ) : (), 310 "" 311 ) . $CRLF . (defined($args->{body}) ? $args->{body} : ""); 312} 313 314our $SOCKET_CACHE = {}; 315 316sub request { 317 my $args = $_[0]; 318 319 # Backwards compatibility for code that provided the old timeout 320 # argument. 321 $args->{connect_timeout} = $args->{read_timeout} = $args->{timeout} if exists $args->{timeout}; 322 323 # Ditto for providing a default socket cache, allow for setting it 324 # to "socket_cache => undef" to disable the cache. 325 $args->{socket_cache} = $SOCKET_CACHE unless exists $args->{socket_cache}; 326 327 # Provide a default for the read_length option 328 $args->{read_length} = 10 * 2 ** 10 unless exists $args->{read_length}; 329 330 # Use $; so we can use the $socket_cache->{$$, $host, $port} 331 # idiom to access the cache. 332 my $cache_key; $cache_key = join($;, $$, @$args{qw(host port)}) if defined $args->{socket_cache}; 333 334 my $soc; 335 if (defined $cache_key and exists $args->{socket_cache}->{$cache_key}) { 336 $soc = $args->{socket_cache}->{$cache_key}; 337 } else { 338 ($soc, my $error) = _construct_socket(@$args{qw(host port connect_timeout)}); 339 return $error if $error; 340 $args->{socket_cache}->{$cache_key} = $soc if defined $cache_key; 341 $args->{on_connect}->() if exists $args->{on_connect}; 342 } 343 344 my $r = _build_http_message($args); 345 my $total = length($r); 346 my $left = $total; 347 348 vec(my $rout = '', fileno($soc), 1) = 1; 349 while ($left > 0) { 350 if (_select(undef, $rout, undef, undef) != 1) { 351 delete $args->{socket_cache}->{$cache_key} if defined $cache_key; 352 return { 353 error => Hijk::Error::REQUEST_SELECT_ERROR, 354 error_message => "Got error on select() before the write() when while writing the HTTP request the socket", 355 errno_number => $!+0, 356 errno_string => "$!", 357 }; 358 } 359 360 my $rc = syswrite($soc,$r,$left, $total - $left); 361 if (!defined($rc)) { 362 next if ($! == EWOULDBLOCK || $! == EAGAIN || $! == EINTR); 363 delete $args->{socket_cache}->{$cache_key} if defined $cache_key; 364 shutdown($soc, 2); 365 return { 366 error => Hijk::Error::REQUEST_WRITE_ERROR, 367 error_message => "Got error trying to write the HTTP request with write() to the socket", 368 errno_number => $!+0, 369 errno_string => "$!", 370 }; 371 } 372 $left -= $rc; 373 } 374 375 my ($close_connection,$proto,$status,$head,$body,$error,$error_message,$errno_number,$errno_string); 376 eval { 377 ($close_connection,$proto,$status,$head,$body,$error,$error_message,$errno_number,$errno_string) = 378 _read_http_message(fileno($soc), @$args{qw(read_length read_timeout parse_chunked head_as_array method)}); 379 1; 380 } or do { 381 my $err = $@ || "zombie error"; 382 delete $args->{socket_cache}->{$cache_key} if defined $cache_key; 383 shutdown($soc, 2); 384 die $err; 385 }; 386 387 if ($status == 0 388 # We always close connections for 1.0 because some servers LIE 389 # and say that they're 1.0 but don't close the connection on 390 # us! An example of this. Test::HTTP::Server (used by the 391 # ShardedKV::Storage::Rest tests) is an example of such a 392 # server. In either case we can't cache a connection for a 1.0 393 # server anyway, so BEGONE! 394 or $close_connection 395 or (defined $proto and $proto eq 'HTTP/1.0')) { 396 delete $args->{socket_cache}->{$cache_key} if defined $cache_key; 397 shutdown($soc, 2); 398 } 399 return { 400 proto => $proto, 401 status => $status, 402 head => $head, 403 body => $body, 404 defined($error) ? ( error => $error ) : (), 405 defined($error_message) ? ( error_message => $error_message ) : (), 406 defined($errno_number) ? ( errno_number => $errno_number ) : (), 407 defined($errno_string) ? ( errno_string => $errno_string ) : (), 408 }; 409} 410 411sub _select { 412 my ($rbits, $wbits, $ebits, $timeout) = @_; 413 while (1) { 414 my $start = Time::HiRes::time(); 415 my $nfound = select($rbits, $wbits, $ebits, $timeout); 416 if ($nfound == -1 && $! == EINTR) { 417 $timeout -= Time::HiRes::time() - $start if $timeout; 418 next; 419 } 420 return $nfound; 421 } 422} 423 4241; 425 426__END__ 427 428=encoding utf8 429 430=head1 NAME 431 432Hijk - Fast & minimal low-level HTTP client 433 434=head1 SYNOPSIS 435 436A simple GET request: 437 438 use Hijk (); 439 my $res = Hijk::request({ 440 method => "GET", 441 host => "example.com", 442 port => "80", 443 path => "/flower", 444 query_string => "color=red" 445 }); 446 447 if (exists $res->{error} and $res->{error} & Hijk::Error::TIMEOUT) { 448 die "Oh noes we had some sort of timeout"; 449 } 450 451 die "Expecting an 'OK' response" unless $res->{status} == 200; 452 453 say $res->{body}; 454 455A POST request, you have to manually set the appropriate headers, URI 456escape your values etc. 457 458 use Hijk (); 459 use URI::Escape qw(uri_escape); 460 461 my $res = Hijk::request({ 462 method => "POST", 463 host => "example.com", 464 port => "80", 465 path => "/new", 466 head => [ "Content-Type" => "application/x-www-form-urlencoded" ], 467 query_string => "type=flower&bucket=the%20one%20out%20back", 468 body => "description=" . uri_escape("Another flower, let's hope it's exciting"), 469 }); 470 471 die "Expecting an 'OK' response" unless $res->{status} == 200; 472 473=head1 DESCRIPTION 474 475Hijk is a fast & minimal low-level HTTP client intended to be used 476where you control both the client and the server, e.g. for talking to 477some internal service from a frontend user-facing web application. 478 479It is C<NOT> a general HTTP user agent, it doesn't support redirects, 480proxies, SSL and any number of other advanced HTTP features like (in 481roughly descending order of feature completeness) L<LWP::UserAgent>, 482L<WWW::Curl>, L<HTTP::Tiny>, L<HTTP::Lite> or L<Furl>. This library is 483basically one step above manually talking HTTP over sockets. 484 485Having said that it's lightning fast and extensively used in 486production at L<Booking.com|https://www.booking.com> where it's used 487as the go-to transport layer for talking to internal services. It uses 488non-blocking sockets and correctly handles all combinations of 489connect/read timeouts and other issues you might encounter from 490various combinations of parts of your system going down or becoming 491otherwise unavailable. 492 493=head1 FUNCTION: Hijk::request( $args :HashRef ) :HashRef 494 495C<Hijk::request> is the only function you should use. It (or anything 496else in this package for that matter) is not exported, so you have to 497use the fully qualified name. 498 499It takes a C<HashRef> of arguments and either dies or returns a 500C<HashRef> as a response. 501 502The C<HashRef> argument to it must contain some of the key-value pairs 503from the following list. The value for C<host> and C<port> are 504mandatory, but others are optional with default values listed below. 505 506 protocol => "HTTP/1.1", # (or "HTTP/1.0") 507 host => ..., 508 port => ..., 509 connect_timeout => undef, 510 read_timeout => undef, 511 read_length => 10240, 512 method => "GET", 513 path => "/", 514 query_string => "", 515 head => [], 516 body => "", 517 socket_cache => \%Hijk::SOCKET_CACHE, # (undef to disable, or \my %your_socket_cache) 518 on_connect => undef, # (or sub { ... }) 519 parse_chunked => 0, 520 head_as_array => 0, 521 no_default_host_header => 1, 522 523Notice how Hijk does not take a full URI string as input, you have to 524specify the individual parts of the URL. Users who need to parse an 525existing URI string to produce a request should use the L<URI> module 526to do so. 527 528The value of C<head> is an C<ArrayRef> of key-value pairs instead of a 529C<HashRef>, this way you can decide in which order the headers are 530sent, and you can send the same header name multiple times. For 531example: 532 533 head => [ 534 "Content-Type" => "application/json", 535 "X-Requested-With" => "Hijk", 536 ] 537 538Will produce these request headers: 539 540 Content-Type: application/json 541 X-Requested-With: Hijk 542 543In addition Hijk will provide a C<Host> header for you by default with 544the C<host> value you pass to C<request()>. To suppress this (e.g. to 545send custom C<Host> requests) pass a true value to the 546C<no_default_host_header> option and provide your own C<Host> header 547in the C<head> C<ArrayRef> (or don't, if you want to construct a 548C<Host>-less request knock yourself out...). 549 550Hijk doesn't escape any values for you, it just passes them through 551as-is. You can easily produce invalid requests if e.g. any of these 552strings contain a newline, or aren't otherwise properly escaped. 553 554The value of C<connect_timeout> or C<read_timeout> is in floating 555point seconds, and is used as the time limit for connecting to the 556host, and reading the response back from it, respectively. The default 557value for both is C<undef>, meaning no timeout limit. If you don't 558supply these timeouts and the host really is unreachable or slow, 559we'll reach the TCP timeout limit before returning some other error to 560you. 561 562The default C<protocol> is C<HTTP/1.1>, but you can also specify 563C<HTTP/1.0>. The advantage of using C<HTTP/1.1> is support for 564keep-alive, which matters a lot in environments where the connection 565setup represents non-trivial overhead. Sometimes that overhead is 566negligible (e.g. on Linux talking to an nginx on the local network), 567and keeping open connections down and reducing complexity is more 568important, in those cases you can either use C<HTTP/1.0>, or specify 569C<Connection: close> in the request, but just using C<HTTP/1.0> is an 570easy way to accomplish the same thing. 571 572By default we will provide a C<socket_cache> for you which is a global 573singleton that we maintain keyed on C<join($;, $$, $host, $port)>. 574Alternatively you can pass in C<socket_cache> hash of your own which 575we'll use as the cache. To completely disable the cache pass in 576C<undef>. 577 578The optional C<on_connect> callback is intended to be used for you to 579figure out from production traffic what you should set the 580C<connect_timeout>. I.e. you can start a timer when you call 581C<Hijk::request()> that you end when C<on_connect> is called, that's 582how long it took us to get a connection. If you start another timer in 583that callback that you end when C<Hijk::request()> returns to you 584that'll give you how long it took to send/receive data after we 585constructed the socket, i.e. it'll help you to tweak your 586C<read_timeout>. The C<on_connect> callback is provided with no 587arguments, and is called in void context. 588 589We have experimental support for parsing chunked responses 590encoding. historically Hijk didn't support this at all and if you 591wanted to use it with e.g. nginx you had to add 592C<chunked_transfer_encoding off> to the nginx config file. 593 594Since you may just want to do that instead of having Hijk do more work 595to parse this out with a more complex and experimental codepath you 596have to explicitly enable it with C<parse_chunked>. Otherwise Hijk 597will die when it encounters chunked responses. The C<parse_chunked> 598option may be turned on by default in the future. 599 600The return value is a C<HashRef> representing a response. It contains 601the following key-value pairs. 602 603 proto => :Str 604 status => :StatusCode 605 body => :Str 606 head => :HashRef (or :ArrayRef with "head_as_array") 607 error => :PositiveInt 608 error_message => :Str 609 errno_number => :Int 610 errno_string => :Str 611 612For example, to send a request to 613C<http://example.com/flower?color=red>, pass the following parameters: 614 615 my $res = Hijk::request({ 616 host => "example.com", 617 port => "80", 618 path => "/flower", 619 query_string => "color=red" 620 }); 621 die "Response is not 'OK'" unless $res->{status} == 200; 622 623Notice that you do not need to put the leading C<"?"> character in the 624C<query_string>. You do, however, need to properly C<uri_escape> the content of 625C<query_string>. 626 627Again, Hijk doesn't escape any values for you, so these values B<MUST> 628be properly escaped before being passed in, unless you want to issue 629invalid requests. 630 631By default the C<head> in the response is a C<HashRef> rather then an 632C<ArrayRef>. This makes it easier to retrieve specific header fields, 633but it means that we'll clobber any duplicated header names with the 634most recently seen header value. To get the returned headers as an 635C<ArrayRef> instead specify C<head_as_array>. 636 637If you want to fiddle with the C<read_length> value it controls how 638much we C<POSIX::read($fd, $buf, $read_length)> at a time. 639 640We currently don't support servers returning a http body without an accompanying 641C<Content-Length> header; bodies B<MUST> have a C<Content-Length> or we won't pick 642them up. 643 644=head1 ERROR CODES 645 646If we had a recoverable error we'll include an "error" key whose value 647is a bitfield that you can check against Hijk::Error::* 648constants. Those are: 649 650 Hijk::Error::CONNECT_TIMEOUT 651 Hijk::Error::READ_TIMEOUT 652 Hijk::Error::TIMEOUT 653 Hijk::Error::CANNOT_RESOLVE 654 Hijk::Error::REQUEST_SELECT_ERROR 655 Hijk::Error::REQUEST_WRITE_ERROR 656 Hijk::Error::REQUEST_ERROR 657 Hijk::Error::RESPONSE_READ_ERROR 658 Hijk::Error::RESPONSE_BAD_READ_VALUE 659 Hijk::Error::RESPONSE_ERROR 660 661In addition we might return C<error_message>, C<errno_number> and 662C<errno_string> keys, see the discussion of C<Hijk::Error::REQUEST_*> 663and C<Hijk::Error::RESPONSE_*> errors below. 664 665The C<Hijk::Error::TIMEOUT> constant is the same as 666C<Hijk::Error::CONNECT_TIMEOUT | Hijk::Error::READ_TIMEOUT>. It's 667there for convenience so you can do: 668 669 .. if exists $res->{error} and $res->{error} & Hijk::Error::TIMEOUT; 670 671Instead of the more verbose: 672 673 .. if exists $res->{error} and $res->{error} & (Hijk::Error::CONNECT_TIMEOUT | Hijk::Error::READ_TIMEOUT) 674 675We'll return C<Hijk::Error::CANNOT_RESOLVE> if we can't 676C<gethostbyname()> the host you've provided. 677 678If we fail to do a C<select()> or C<write()> during when sending the 679response we'll return C<Hijk::Error::REQUEST_SELECT_ERROR> or 680C<Hijk::Error::REQUEST_WRITE_ERROR>, respectively. Similarly to 681C<Hijk::Error::TIMEOUT> the C<Hijk::Error::REQUEST_ERROR> constant is 682a union of these two, and any other request errors we might add in the 683future. 684 685When we're getting the response back we'll return 686C<Hijk::Error::RESPONSE_READ_ERROR> when we can't C<read()> the 687response, and C<Hijk::Error::RESPONSE_BAD_READ_VALUE> when the value 688we got from C<read()> is C<0>. The C<Hijk::Error::RESPONSE_ERROR> 689constant is a union of these two and any other response errors we 690might add in the future. 691 692Some of these C<Hijk::Error::REQUEST_*> and C<Hijk::Error::RESPONSE_*> 693errors are re-thrown errors from system calls. In that case we'll also 694pass along C<error_message> which is a short human readable error 695message about the error, as well as C<errno_number> & C<errno_string>, 696which are C<$!+0> and C<"$!"> at the time we had the error. 697 698Hijk might encounter other errors during the course of the request and 699B<WILL> call C<die> if that happens, so if you don't want your program 700to stop when a request like that fails wrap it in C<eval>. 701 702Having said that the point of the C<Hijk::Error::*> interface is that 703all errors that happen during normal operation, i.e. making valid 704requests against servers where you can have issues like timeouts, 705network blips or the server thread on the other end being suddenly 706kill -9'd should be caught, categorized and returned in a structural 707way by Hijk. 708 709We're not currently aware of any issues that occur in such normal 710operations that aren't classified as a C<Hijk::Error::*>, and if we 711find new issues that fit the criteria above we'll likely just make a 712new C<Hijk::Error::*> for it. 713 714We're just not trying to guarantee that the library can never C<die>, 715and aren't trying to catch truly exceptional issues like 716e.g. C<fcntl()> failing on a valid socket. 717 718=head1 AUTHORS 719 720Kang-min Liu <gugod@gugod.org> 721 722Ævar Arnfjörð Bjarmason <avar@cpan.org> 723 724Borislav Nikolov <jack@sofialondonmoskva.com> 725 726Damian Gryski <damian@gryski.com> 727 728=head1 COPYRIGHT 729 730Copyright (c) 2013- Kang-min Liu C<< <gugod@gugod.org> >>. 731 732=head1 LICENCE 733 734The MIT License 735 736=head1 DISCLAIMER OF WARRANTY 737 738BECAUSE THIS SOFTWARE IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 739FOR THE SOFTWARE, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 740OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 741PROVIDE THE SOFTWARE "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER 742EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 743WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE 744ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE IS WITH 745YOU. SHOULD THE SOFTWARE PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL 746NECESSARY SERVICING, REPAIR, OR CORRECTION. 747 748IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 749WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 750REDISTRIBUTE THE SOFTWARE AS PERMITTED BY THE ABOVE LICENCE, BE 751LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL, 752OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE 753THE SOFTWARE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING 754RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A 755FAILURE OF THE SOFTWARE TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF 756SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 757SUCH DAMAGES. 758 759=cut 760