POEx-Role-PSGIServer
view release on metacpan or search on metacpan
lib/POEx/Role/PSGIServer.pm view on Meta::CPAN
|| ($code == 304);
if ($no_body_allowed) {
$self->_write($c, "\r\n");
$self->close($c);
return Plack::Util::FALSE;
}
return Plack::Util::TRUE;
}
method respond(PSGIServerContext $c, PSGIResponse $response) is Event {
$self->http_preamble($c, $response);
$self->process_headers($c, $response);
return unless ($self->http_body_allowed($c, $response));
$self->_write($c, "Transfer-Encoding: chunked\r\n") if $c->{chunked};
$self->_write($c, "\r\n");
my $body = $response->[2];
if ($body) {
# If we have a real filehandle, build a Streamer
if (Plack::Util::is_real_fh($body)) {
# flush and destroy the old wheel, since the Streamer will build a new one
$c->{wheel}->flush();
$self->delete_wheel($c->{wheel}->ID);
my $handle = (delete $c->{wheel})->get_input_handle();
my $streamer = POEx::Role::PSGIServer::Streamer->new(
input_handle => $body,
output_handle => $handle,
server_context => $c,
);
}
# If we don't just iterate the lines
else {
Plack::Util::foreach($body, sub{$self->write($c, @_)});
$self->close($c);
}
return;
}
# If there was no body, we need to build a push writer
return $self->generate_push_writer($c);
}
method generate_push_writer(PSGIServerContext $c) returns (Object) {
return POEx::Role::PSGIServer::ProxyWriter->new(server_context => $c, proxied => $self);
}
method generate_psgi_env(PSGIServerContext $c) returns (HashRef) {
return req_to_psgi(
$c->{request},
SERVER_NAME => $self->listen_ip,
SERVER_PORT => $self->listen_port,
SERVER_PROTOCOL => $c->{protocol},
'psgi.streaming' => Plack::Util::TRUE,
'psgi.nonblocking' => Plack::Util::TRUE,
'psgi.runonce' => Plack::Util::FALSE,
);
}
method build_server_context(HTTPRequest $req, WheelID $wheel_id) returns (PSGIServerContext) {
my $version = $req->header('X-HTTP-Version') || '0.9';
my $protocol = "HTTP/$version";
my $connection = $req->header('Connection') || '';
my $keep_alive = ($version eq '1.1' && $connection ne 'close');
my $context = {
request => $req,
wheel => $self->get_wheel($wheel_id),
version => $version,
protocol => $protocol,
connection => $connection,
keep_alive => $keep_alive,
explicit_length => 0,
};
return $context;
}
method handle_inbound_data(HTTPRequest $req, WheelID $wheel_id) is Event {
my $context = $self->build_server_context($req, $wheel_id);
my $env = $self->generate_psgi_env($context);
my $response = Plack::Util::run_app($self->psgi_app, $env);
if (ref($response) eq 'CODE') {
$response->(sub { $self->respond($context, @_) });
}
else {
$self->yield('respond', $context, $response);
}
}
method run(CodeRef $app) {
$self->register_service($app);
POE::Kernel->run();
}
method handle_on_flushed(WheelID $id) is Event {
if ($self->has_wheel_flusher($id)) {
$self->get_wheel_flusher($id)->();
}
1;
}
after delete_wheel(WheelID $id) {
$self->clear_wheel_flusher($id);
}
with 'POEx::Role::TCPServer' => {
-excludes => [
qw/handle_socket_error handle_listen_error handle_on_flushed/
]
};
}
__END__
=pod
=head1 NAME
POEx::Role::PSGIServer - (DEPRECATED) Encapsulates core PSGI server behavior
=head1 VERSION
version 1.150280
=head1 SYNOPSIS
use MooseX::Declare;
class MyServer with POEx::Role::PSGIServer { }
MyServer->new()->run($some_psgi_app);
=head1 DESCRIPTION
This module has been deprecated.
POEx::Role::PSGIServer encapsulates the core L<PSGI> server behaviors into an easy to consume and extend role. It is based on previous POEx work such as POEx::Role::TCPServer which provides basic TCP socket multiplexing via POE::Wheel::SocketFactory ...
=head2 RATIONALE
This Role has its roots firmly planted in POE::Component::Server::PSGI which provided the initial seed with the layout and logic of the basic server. Unfortunately, POE::Component::Server::PSGI didn't provide any mechnism for extension. The main goal...
=head1 CLASS_METHODS
=head2 around BUILDARGS
(ClassName $class: @args)
BUILDARGS is wrapped to translate from the expected Plack::Handler interface to POEx::Role::TCPServer's expected interface.
=head1 PUBLIC_ATTRIBUTES
=head2 psgi_app
is: ro, isa: CodeRef, writer: register_service
This attribute stores the PSGI application to be run from this server. A writer method is provided to match the expected Plack::Handler interface
=head1 PROTECTED_ATTRIBUTES
=head2 wheel_flushers
is: ro, isa: HashRef,
exists : has_wheel_flusher,
get : get_wheel_flusher,
set : set_wheel_flusher,
delete : clear_wheel_flusher
This attribute stores coderefs to be called on a wheel's flush event
(necessary to properly handle poll_cb)
=head1 PUBLIC_METHODS
=head2 run
(CodeRef $app)
run is provided to complete the Plack::Handler interface and allow the server to be executed with the provided psgi app
=head1 PROTECTED_METHODS
=head2 after _start
is Event
_start is advised to supply the proper input (HTTP::Parser) and output (Stream) filters.
=head2 write
(PSGIServerContext $c, Str $data)
write will alter the data if necessary for a chunked transfer encoded response and send it to the output buffer for the current context
=head2 close
(PSGIServerContext $c)
close will close the connection for the current context, but flushing the output buffer first
=head2 handle_socket_error
( run in 0.599 second using v1.01-cache-2.11-cpan-140bd7fdf52 )