view release on metacpan or search on metacpan
0.09 Tuesday 23rd May, 2006
Fixed for newer versions of POE where POE::Filter::HTTPD has
changed representation from hashref to arrayref.
0.08 Friday 2nd September, 2005
Added documentation and tests for streaming mode from Philip Gwyn.
Fixes for rt.cpan.org bugs #6747, #11349
Fixed t/30_error.t's call to Test::Builder.
0.07 Tuesday 22nd March, 2005
Make the test for 'close' in the Connection: close case
insensitive (iPhoto 5 fixup from Dieter Mücke)
0.06 Sunday 2nd January, 2005
Added status messages to t/10_run.t
Added default ErrorHandler, that prints a simple message to STDERR
lib/POE/Component/Server/HTTP.pm view on Meta::CPAN
if( $state eq 'ErrorHandler') {
warn "ErrorHandler is not allowed to return RC_WAIT";
}
else {
last HANDLERS;
}
}
next;
}
elsif ($state eq 'Cleanup') {
if (not $response->is_error and $response->streaming()) {
$_[HEAP]->{wheels}->{$id}->set_output_filter(POE::Filter::Stream->new() );
unshift(@{$handlers->{Queue}},'Streaming');
next HANDLERS;
}
delete($response->{connection});
delete($request->{connection});
# under HTTP/1.1 connections are always kept alive, unless
# there's a Connection: close present
lib/POE/Component/Server/HTTP.pm view on Meta::CPAN
sub state_Send {
my $self = shift;
my $response = shift;
my $wheel = shift;
$response->header(%{$self->{Headers}});
unless ($response->header('Date')) {
$response->header('Date',time2str(time));
}
if (!($response->header('Content-Lenth')) && !($response->streaming())) {
use bytes;
$response->header('Content-Length',length($response->content));
}
$wheel->put($response);
}
1;
__END__
lib/POE/Component/Server/HTTP.pm view on Meta::CPAN
with apache. If you want /honk to act like a directory, you should have
a handler for /honk which redirects to /honk/.
However, there can be only one ContentHandler and if any handler installs
a ContentHandler that will override the old ContentHandler.
If no handler installs a ContentHandler it will find the closest one
directory wise and use it.
There is also a special StreamHandler which is a coderef that gets
invoked if you have turned on streaming by doing
$response->streaming(1);
Handlers take the $request and $response objects as arguments.
=over 4
=item RC_OK
Everything is ok, please continue processing.
=item RC_DENY
lib/POE/Component/Server/HTTP.pm view on Meta::CPAN
before the ContentHandler. They can change ContentHandler (but beware,
other PreHandlers might also change it) and push on PostHandlers.
new(PreHandler => { '/' => [sub {}], '/foo/' => [\&foo]});
=item ContentHandler
The handler that is supposed to give the content. When this handler
returns it will send the response object to the client. It will
automaticly add Content-Length and Date if these are not set. If the
response is streaming it will make sure the correct headers are
set. It will also expand any cookies which have been pushed onto the
response object.
new(ContentHandler => { '/' => sub {}, '/foo/' => \&foo});
=item ErrorHandler
This handler is called when there is a read or write error on the socket.
This is most likely caused by the remote side closing the connection.
$resquest->is_error and $response->is_error will return true. Note that
lib/POE/Component/Server/HTTP.pm view on Meta::CPAN
=item PostHandler
These handlers are run after the socket has been flushed.
new(PostHandler => { '/' => [sub {}], '/foo/' => [\&foo]});
=item StreamHandler
If you turn on streaming in any other handler, the request is placed in
streaming mode. This handler is called, with the usual parameters, when
streaming mode is first entered, and subsequently when each block of data is
flushed to the client.
Streaming mode is turned on via the C<$response> object:
$response->streaming(1);
You deactivate streaming mode with the same object:
$response->close;
Content is also sent to the client via the C<$response> object:
$response->send($somedata);
The output filter is set to POE::Filter::Stream, which passes the data
through unchanged. If you are doing a multipart/mixed response, you will
have to set up your own headers.
lib/POE/Component/Server/HTTP.pm view on Meta::CPAN
.....
POE::Component::Filter::HTTP->new(
ContentHandler => { '/someurl' => sub { $self->someurl(@_) },
StreamHandler => sub { $self->stream(@_),
);
}
sub someurl {
my($self, $resquest, $response)=@_;
$self->{todo} = [ .... ];
$response->streaming(1);
$response->code(RC_OK); # you must set up your response header
$response->content_type(...);
return RC_OK;
}
sub stream {
my($self, $resquest, $response)=@_;
if( @{$self->{todo}} ) {
$response->send(shift @{$self->{todo}});
}
else {
$response->close;
}
}
Another example can be found in t/30_stream.t. The parts dealing with
multipart/mixed are well documented and at the end of the file.
NOTE: Changes in streaming mode are only verified when StreamHandler exits.
So you must either turn streaming off in your StreamHandler, or make sure
that the StreamHandler will be called again. This last is done by sending
data to the client. If for some reason you have no data to send, you can
get the same result with C<continue>. Remember that this will also cause the
StreamHandler to be called one more time.
my $aliases=POE::Component::Filter::HTTP->new( ....);
# and then, when the end of the stream in met
$response->close;
$response->continue;
lib/POE/Component/Server/HTTP.pm view on Meta::CPAN
=head1 TODO
=over 4
=item Document Connection Response and Request objects.
=item Write more tests
=item Add a PoCo::Server::HTTP::Session that matches a http session against poe session using cookies or other state system
=item Add more options to streaming
=item Figure out why post()ed C<shutdown> events don't get received.
=item Probably lots of other API changes
=back
=head1 AUTHOR
Arthur Bergman, arthur@contiller.se
lib/POE/Component/Server/HTTP/Response.pm view on Meta::CPAN
use strict;
package POE::Component::Server::HTTP::Response;
use vars qw(@ISA);
use HTTP::Response;
@ISA = qw(HTTP::Response);
use POE;
sub streaming {
my $self = shift;
if (@_) {
if ($_[0]) {
$self->{streaming} = 1;
}
else {
$self->{streaming} = 0;
}
}
return $self->{streaming};
}
sub is_error {
my $self = shift;
if (@_) {
if ($_[0]) {
$self->{is_error} = 1;
}
else {
$self->{is_error} = 0;
lib/POE/Component/Server/HTTP/Response.pm view on Meta::CPAN
}
sub continue {
my $self = shift;
$poe_kernel->post($self->{connection}->{session},
'execute' => $self->{connection}->{my_id});
}
sub close {
my $self = shift;
$self->{streaming} = 0;
shift @{$self->{connection}->{handlers}->{Queue}};
}
1;
t/20_stream.t view on Meta::CPAN
#######################################
# Called as ContentHandler
sub multipart
{
my($self, $request, $response)=@_;
DEBUG and warn "multipart\n";
# Send an HTTP header and turn streaming on
$self->multipart_start($request, $response);
# After the HTTP header is sent, our StreamHandler will be called
# Save the values that stream_start needs to do its work
push @{$self->{stream_todo}}, [$request, $response,
'first.gif', 'last.gif'];
return RC_OK;
}
#######################################
t/20_stream.t view on Meta::CPAN
{
my($self, $ct, $resp)=@_;
$resp ||= HTTP::Response->new;
$resp->content_type($ct||'text/plain');
$resp->code(200);
return $resp;
}
#######################################
# Send an HTTP header that sets up multipart/mixed response
# Also turns on streaming.
#
# PoCo::Server::HTTP will send the $response object, then run PostHandler
# then switch to Streaming mode.
sub multipart_start
{
my($self, $request, $response)=@_;
$response->code(RC_OK);
$self->{boundary} ||= 'ThisRandomString';
$response->content_type("multipart/mixed;boundary=$self->{boundary}");
$response->streaming(1);
}
#######################################
# The request is done. Turn off streaming and end the multipart response
# Setting the header Connection to 'close' forces PoCo::Server::HTTP to
# close the socket. This is needed so that the browsers stop "twirling".
sub multipart_end
{
my($self, $request, $response)=@_;
DEBUG and warn "Closing connection\n";
$response->close;
$request->header(Connection => 'close');
$response->send("--$self->{boundary}--\cM\cJ");
}
sub callback {
my $request = shift;
my $response = shift;
my $connection = $request->connection;
#my $cookie = CGI::Cookie->new(-name => "FOO", -value => "bar");
$response->code('200');
$response->push_header("Content-type", "text/html");
#$response->push_header('Set-Cookie' => $cookie->as_string);
$response->content("Welcome ".$connection->remote_ip);
# $response->streaming(1);
return $response;
}
$poe_kernel->run();