Skip Menu |

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

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

People
Owner: Nobody in particular
Requestors: normalperson [...] yhbt.net
Cc:
AdminCc:

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



Subject: [PATCH] NB: set http_bytes if read_entity_body hits EAGAIN on first read
Date: Fri, 6 Jul 2012 01:25:39 +0000
To: bug-Net-HTTP [...] rt.cpan.org
From: Eric Wong <normalperson [...] yhbt.net>
If read_entity_body is called before a response body is readable, http_bytes is never set. This causes future calls of read_entity_body to never return zero (EOF). I encountered this issue on 6.01 and 6.03. The new test case illustrates the issue this patch fixes. note: commit 88ecea4531de4178603a6453fc73e2cf2b53a6e5 breaks all usage of Net::HTTP::NB in which the user expects EAGAIN. I needed to revert 88ecea4531de4178603a6453fc73e2cf2b53a6e5 before testing this patch. --- lib/Net/HTTP/Methods.pm | 3 +-- t/http-nb.t | 52 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+), 2 deletions(-) create mode 100644 t/http-nb.t diff --git a/lib/Net/HTTP/Methods.pm b/lib/Net/HTTP/Methods.pm index cd5e857..e4e41cd 100644 --- a/lib/Net/HTTP/Methods.pm +++ b/lib/Net/HTTP/Methods.pm @@ -565,8 +565,7 @@ sub read_entity_body { my $n = $bytes; $n = $size if $size && $size < $n; $n = my_read($self, $$buf_ref, $n); - return undef unless defined $n; - ${*$self}{'http_bytes'} = $bytes - $n; + ${*$self}{'http_bytes'} = defined $n ? $bytes - $n : $bytes; return $n; } else { diff --git a/t/http-nb.t b/t/http-nb.t new file mode 100644 index 0000000..b3dafe0 --- /dev/null +++ b/t/http-nb.t @@ -0,0 +1,52 @@ +#!perl -w + +use strict; +use Test; + +plan tests => 14; + +require Net::HTTP::NB; +use IO::Socket::INET; +use Data::Dumper; +use IO::Select; +use Socket qw(TCP_NODELAY); +my $buf; + +# bind a random TCP port for testing +my %lopts = ( + LocalAddr => "127.0.0.1", + LocalPort => 0, + Proto => "tcp", + ReuseAddr => 1, + Listen => 1024 +); + +my $srv = IO::Socket::INET->new(%lopts); +ok(ref($srv), "IO::Socket::INET"); +my $host = $srv->sockhost . ':' . $srv->sockport; +my $nb = Net::HTTP::NB->new(Host => $host, Blocking => 0); +ok(ref($nb), "Net::HTTP::NB"); +ok(IO::Select->new($nb)->can_write(3), 1); + +ok($nb->write_request("GET", "/")); +my $acc = $srv->accept; +ok(ref($acc), "IO::Socket::INET"); +$acc->sockopt(TCP_NODELAY, 1); +ok($acc->sysread($buf, 4096)); +ok($acc->syswrite("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n")); + +ok(1, IO::Select->new($nb)->can_read(3)); +my @r = $nb->read_response_headers; +ok($r[0], 200); + +# calling read_entity_body before response body is readable causes +# EOF to never happen eventually +ok(!defined($nb->read_entity_body($buf, 4096)) && $!{EAGAIN}); + +ok($acc->syswrite("hello"), 5, "server wrote response body"); + +ok(IO::Select->new($nb)->can_read(3), 1, "client body is readable"); +ok($nb->read_entity_body($buf, 4096), 5, "client gets 5 bytes"); + +# this fails if we got EAGAIN from the first read_entity_body call: +ok($nb->read_entity_body($buf, 4096), 0, "client gets EOF"); -- Eric Wong
 Thanks.  Applied in 6.04.  I fixed the can_read() issue by dropping of a dummy override in Net::HTTP::NB.