Subject: | If server closes connection before sending headers 406 generated |
Hello
Since version 0.80, "406 Not Acceptable" response generated when server
closes connection wihout sending headers. Earlier was sent "400 Bad
Request/Incomplete response" which was correct behavior.
I browsed through changelog and found that 400 Bad request/Incomplete
Response was generated when response was greater then MaxSize. So change
of code to 406 broke handling of situation which I described.
I created a test case (which make situation with closing connection
before sending any response) which shows the response received. And a
patch to fix the problem (it adds handling for such case but does not
break handling of MaxSize overflow).
Here is the test output with unfixed PoCoCl::HTTP:
406 Not Acceptable
<html>
<HEAD><TITLE>Error: Not Acceptable</TITLE></HEAD>
<BODY>
<H1>Error: Not Acceptable</H1>
Response larger than MaxSize - 1
</BODY>
</HTML>
And here is the test output for the fixed version:
400 Bad Request
<html>
<HEAD><TITLE>Error: Bad Request</TITLE></HEAD>
<BODY>
<H1>Error: Bad Request</H1>
incomplete response 1
</BODY>
</HTML>
Subject: | 406_error.patch |
Index: lib/POE/Component/Client/HTTP.pm
===================================================================
--- lib/POE/Component/Client/HTTP.pm (revision 311)
+++ lib/POE/Component/Client/HTTP.pm (working copy)
@@ -531,6 +539,11 @@
$request->[REQ_STATE] = RS_DONE;
$request->return_response;
return;
+ } else {
+ unless ($request->[REQ_STATE] & RS_POSTED) {
+ $request->error(400, "incomplete response $request_id");
+ return;
+ }
}
}
Subject: | test_406.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 { print $_[ARG1]->[0]->as_string, $_[KERNEL]->post(webserver => 'shutdown') }
}
);
POE::Component::Server::TCP->new
(
Alias => 'webserver',
Address => '127.0.0.1',
Port => 0,
ClientInput => \&handle_request,
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}->shutdown_output;
}