Skip Menu |
 

This queue is for tickets about the POE-Component-Client-HTTP CPAN distribution.

Report information
The Basics
Id: 25855
Status: resolved
Priority: 0/
Queue: POE-Component-Client-HTTP

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

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



Subject: POE::Filter::HTTPChunk hangs on invalid chunked response
Download (untitled) / with headers
text/plain 977b
Hello I noticed a probmem. When trailer of chunked response is not valid the POE::Filter::HTTPChunk module start eating 100% CPU and loop inside POE::Filter::HTTPChunk::get_one (it tries to parse trailing headers again and again, but since it does not match expeced regular expressions chunk is not modified and loop is endless ...) I created the test case (attached) to demonstrate this. I'm not sure how better to fix this, so I'm just sending a test case. Maybe just start to skip lines until all input from server will be exhausted and connection will be closed by keepalive timeout. Better approach is to return to client error message and close connection. Possible solution is to pass PoCoCl::HTTP::Request object to Filter::HTTPChunk constructor so Filter::HTTPChunk will be able to close connection in case of error, but it seems that this creates circular references (betwen request and filter, there will be indirect loop request -> wheel -> filter -> request)
Subject: testcase.pl
Download testcase.pl
text/x-perl 1.3k
#! /usr/bin/perl use strict; use warnings; use POE qw(Component::Server::TCP Component::Client::HTTP Filter::HTTPD); use HTTP::Request::Common qw(GET); use Socket; POE::Component::Client::HTTP->spawn(Alias => 'UA'); POE::Session->create ( inline_states => { _start => sub { $_[KERNEL]->alias_set('main') }, set_port => sub { $_[KERNEL]->post(UA => request => response => GET "http://127.0.0.1:$_[ARG0]/") }, response => sub { $_[KERNEL]->post(webserver => 'shutdown') } }, ); POE::Component::Server::TCP->new ( Alias => 'webserver', Address => '127.0.0.1', Port => 0, ClientInput => \&handle_request, ClientFlushed => sub { $_[HEAP]->{client}->shutdown_output }, ClientInputFilter => 'POE::Filter::HTTPD', ClientOutputFilter => 'POE::Filter::Stream', Started => sub { my ($kernel, $heap) = @_[KERNEL, HEAP]; my $port = (sockaddr_in($heap->{listener}->getsockname))[0]; $kernel->post('main', 'set_port', $port); } ); POE::Kernel->run; sub handle_request { my ($kernel, $heap, $request) = @_[KERNEL, HEAP, ARG0]; if ($request->isa("HTTP::Response")) { $heap->{client}->put($request); $kernel->yield("shutdown"); return; } $heap->{client}->put(<<EOD); HTTP/1.1 200 OK Transfer-Encoding: chunked b hello world 0 some junk in trailer EOD }
Download (untitled) / with headers
text/plain 714b
I found easy and elegant solution for this problem. My point is to return $retval, anyway, even if we unable to parse headers we return empty array reference. AFAIR empty array reference meant that there is not enough data passed to filter to produce any filtered entity. And it is true for this case, since if we unable to parse headers that is possible because not enough data. So it will fix two problems: 1. (my original case) if headers are wrong, it will return empty array reference again and again (upon receiving more data if it is) and connection will be terminated by timeout. 2. if headers are correct, but data was not fully retreiven it will just give control back to be able to receive more data.
Index: lib/POE/Filter/HTTPChunk.pm =================================================================== --- lib/POE/Filter/HTTPChunk.pm (revision 311) +++ lib/POE/Filter/HTTPChunk.pm (working copy) @@ -163,11 +163,10 @@ my $headers = delete $self->[TRAILER_HEADERS]; push (@$retval, $headers); - DEBUG and warn "returning ", scalar @$retval, "responses"; - unshift (@{$self->[FRAMING_BUFFER]}, $chunk) if (length $chunk); - return $retval; } - unshift (@{$self->[FRAMING_BUFFER]}, $chunk); + DEBUG and warn "returning ", scalar @$retval, "responses"; + unshift (@{$self->[FRAMING_BUFFER]}, $chunk) if (length $chunk); + return $retval; } } return $retval;
Thanks for the patch. Resolved in revision 354, which will be part of the 0.88 release.


This service is sponsored and maintained by Best Practical Solutions and runs on Perl.org infrastructure.

Please report any issues with rt.cpan.org to rt-cpan-admin@bestpractical.com.