Subject: | POE::Filter::HTTPChunk hangs on invalid chunked response |
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 |
#! /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
}