Skip Menu |

This queue is for tickets about the Net-HTTP CPAN distribution.

Report information
The Basics
Id: 107770
Status: resolved
Priority: 0/
Queue: Net-HTTP

People
Owner: Nobody in particular
Requestors: oleg [...] cpan.org
Cc:
AdminCc:

Bug Information
Severity: (no value)
Broken in: (no value)
Fixed in: (no value)



Subject: Incorrect example of Net::HTTP::NB usage
In SYNOPSIS section we can see an example of how you can send request and read response with Net::HTTP::NB. But this example has potential problems. Let's see this test server: use strict; use IO::Socket; my $serv = IO::Socket::INET->new(Listen => 10, LocalPort => 8080) or die $@; my $body = 'This is the body'; my $header = join( "\r\n", "HTTP/1.1 200 OK", "Server: nginx/1.0.4", "Date: Thu, 06 Oct 2011 16:14:01 GMT", "Content-Type: text/html", "Content-Length: ".length($body), "Connection: keep-alive", "Vary: Accept-Encoding", "X-Powered-By: PHP/5.3.6", "\r\n" ); while (warn("waiting for next request...\n") and my $client = $serv->accept()) { my $req; while ($req !~ /\r\n\r\n$/) { $client->sysread($req, 1024, length $req) or die $!; } $client->syswrite($header.$body); <$client>; # keep-alive ;) } __END__ And this client (a little reworked example from SYNOPSIS): use strict; use Net::HTTP::NB; my $s = Net::HTTP::NB->new(Host => "localhost:8080") || die $@; $s->write_request(GET => "/", 'User-Agent' => "Mozilla/5.0"); use IO::Select; my $sel = IO::Select->new($s); READ_HEADER: { die "Header timeout" unless $sel->can_read(10); my($code, $mess, %h) = $s->read_response_headers; redo READ_HEADER unless $code; } while (1) { die "Body timeout" unless $sel->can_read(10); my $buf; my $n = $s->read_entity_body($buf, 1024); last unless $n; print $buf; } __END__ And output of this client will be "Body timeout" error, instead of expected "This is the body" body content. The problem is that Net::HTTP::Methods internally uses a buffer when reading data from the server. Here read_response_headers() call readed both headers and data, returned headers for us and stored body in the buffer. So, body now in the buffer instead of a socket and socket will not be available for read anymore (until server will close connection, but our uses keep-alive, so will not do it). This is why our can_read(10) call timed out after 10 seconds. And this is how this example may looks like to work properly: use strict; use Net::HTTP::NB; use Errno qw/EAGAIN EWOULDBLOCK/; my $s = Net::HTTP::NB->new(Host => "localhost:8080", KeepAlive => 1) || die $@; $s->write_request(GET => "/", 'User-Agent' => "Mozilla/5.0"); use IO::Select; my $sel = IO::Select->new($s); READ_HEADER: { die "Header timeout" unless $sel->can_read(10); my($code, $mess, %h) = $s->read_response_headers; redo READ_HEADER unless $code; } # Net::HTTP::NB uses internal buffer, so we should check it before # socket check by calling read_entity_body() # make socket non-blocking, so read_entity_body() will not block $s->blocking(0); while (1) { my $buf; my $n; # try to read until error or all data received while (1) { my $tmp_buf; $n = $s->read_entity_body($tmp_buf, 1024); if ($n == -1 || (!defined($n) && ($! == EWOULDBLOCK || $! == EAGAIN))) { last; # no data available this time } elsif ($n) { $buf .= $tmp_buf; # data received } elsif (defined $n) { last; # $n == 0, all readed } else { die "Read error occured: ", $!; # $n == undef } } print $buf if length $buf; last if defined $n && $n == 0; # all readed die "Body timeout" unless $sel->can_read(10); # wait for new data } __END__ The bad news is that most modules which uses Net::HTTP::NB doing it wrong, as showed in the example from the documentation.