Plack-Handler-FCGI-EV
view release on metacpan or search on metacpan
lib/Plack/Handler/FCGI/EV.pm view on Meta::CPAN
}
$sock or die "Couldn't launch FCGI daemon on $listen";
warn "Running FCGI daemon on $listen\n";
# HACK: we return an object and pass it to handler_class. Because it works, and is cleaner
my $handler = Plack::Handler::FCGI::EV::Handler->factory($app);
my $w = EV::io $sock, EV::READ, sub {
my $client = $sock->accept or die "No socket";
$client->blocking(0);
FCGI::EV->new( $client, $handler );
};
$self->{_sock} = $sock;
$self->{_guard} = $w;
return $self;
}
sub run {
my $self = shift;
$self->register_service(@_);
# Could use EV::run, but this is prone to a crash due to:
# syswrite() on closed filehandle GEN1653 at .../lib/site_perl/5.12.3/IO/Stream/EV.pm line 160.
# At least AnyEvent will catch these errors
# EV::run;
AE::cv->recv;
}
package Plack::Handler::FCGI::EV::Handler;
use strict;
use Plack::Util;
use Carp ();
use URI::Escape;
sub factory {
my($class, $app) = @_;
bless { app => $app }, $class;
}
# HACK: This is called from FCGI::EV - but it's actually an instance
# method since we pass our own object to 'handler_class'.
sub new {
my $factory = shift;
my ($server, $env) = @_;
my $app = $factory->{app};
$env = {
SCRIPT_NAME => '',
'psgi.version' => [ 1, 0 ],
'psgi.errors' => *STDERR,
'psgi.url_scheme' => 'http',
'psgi.nonblocking' => 1,
'psgi.streaming' => 1,
'psgi.multithread' => 0,
'psgi.multiprocess' => 1,
'psgi.run_once' => 0,
'psgix.input.buffered' => 1,
%$env,
};
my $request_uri = $env->{REQUEST_URI};
my ( $file, $query_string ) = ( $request_uri =~ /([^?]*)(?:\?(.*))?/s ); # split at ?
$env->{PATH_INFO} = URI::Escape::uri_unescape $file;
$env->{QUERY_STRING} = $query_string || '';
$env->{SERVER_NAME} =~ s/:\d+$//;
# warn Dumper $env;
my $self = {
stdin => '',
server => $server,
env => $env,
app => $app,
};
bless $self, ref $factory;
}
# not support Async Input yet
sub stdin {
my ($self, $stdin, $is_eof) = @_;
$self->{stdin} .= $stdin;
if ($is_eof) {
open my $input, "<", \$self->{stdin};
$self->{env}->{'psgi.input'} = $input;
$self->run_app;
}
}
sub run_app {
my $self = shift;
my $res = Plack::Util::run_app $self->{app}, $self->{env};
if (ref $res eq 'ARRAY') {
$self->handle_response($res);
} elsif (ref $res eq 'CODE') {
$res->(sub { $self->handle_response($_[0]) });
} else {
Carp::croak("Unknown response: $res");
}
}
sub handle_response {
my($self, $res) = @_;
my $hdrs = "Status: $res->[0]\r\n";
Plack::Util::header_iter $res->[1], sub {
$hdrs .= "$_[0]: $_[1]\r\n";
};
$hdrs .= "\r\n";
$self->{server}->stdout($hdrs);
if (defined $res->[2]) {
my $cb = sub { $self->{server}->stdout( $_[0] ) };
Plack::Util::foreach( $res->[2], $cb );
( run in 2.059 seconds using v1.01-cache-2.11-cpan-9789f410c06 )