File Coverage

blib/lib/Plack/Handler/AnyEvent/FCGI.pm
Criterion Covered Total %
statement 24 71 33.8
branch 0 14 0.0
condition 0 4 0.0
subroutine 8 18 44.4
pod 0 4 0.0
total 32 111 28.8


line stmt bran cond sub pod time code
1             package Plack::Handler::AnyEvent::FCGI;
2              
3 2     2   50102 use strict;
  2         5  
  2         75  
4 2     2   45 use 5.008_001;
  2         40  
  2         146  
5             our $VERSION = '0.01';
6              
7 2     2   3688 use AnyEvent;
  2         13263  
  2         76  
8 2     2   1837 use AnyEvent::FCGI;
  2         120984  
  2         183  
9 2     2   3928 use Plack::Util;
  2         39253  
  2         77  
10 2     2   2092 use IO::Handle::Util qw(io_from_write_cb);
  2         70301  
  2         18  
11 2     2   3010 use URI;
  2         14571  
  2         80  
12 2     2   23 use URI::Escape;
  2         3  
  2         2208  
13              
14             sub new {
15 0     0 0   my($class, %args) = @_;
16 0           bless { %args }, $class;
17             }
18              
19             sub run {
20 0     0 0   my $self = shift;
21 0           $self->register_service(@_);
22 0           $self->{_cv}->recv;
23             }
24              
25             sub register_service {
26 0     0 0   my($self, $app) = @_;
27              
28 0 0         my $listen = $self->{listen}[0]
29             or die "listen address/socket not specified";
30              
31 0           my %args;
32 0 0         if ($listen =~ /:\d+$/) {
33 0           @args{qw(host port)} = split /:/, $listen, 2;
34 0 0         $args{host} = undef if $args{host} eq '';
35             } else {
36 0           $args{socket} = $listen;
37             }
38              
39 0           warn "Listening on $listen for FCGI connections\n";
40              
41             $self->{_server} = AnyEvent::FCGI->new(
42             %args,
43 0     0     on_request => sub { $self->_on_request($app, @_) },
44 0           );
45              
46 0           $self->{_cv} = AE::cv;
47             }
48              
49             sub _on_request {
50 0     0     my($self, $app, $request) = @_;
51              
52 0           my $env = $request->params;
53              
54             # deal with ligttpd/nginx path normalization
55 0           my $uri = URI->new("http://localhost" . $env->{REQUEST_URI});
56 0           $env->{PATH_INFO} = URI::Escape::uri_unescape($uri->path);
57 0           $env->{PATH_INFO} =~ s/^\Q$env->{SCRIPT_NAME}\E//;
58              
59             $env = {
60             %$env,
61             'psgi.version' => [1,1],
62             'psgi.url_scheme' => ($env->{HTTPS}||'off') =~ /^(?:on|1)$/i ? 'https' : 'http',
63 0   0       'psgi.input' => do { open my $io, "<", \$request->read_stdin || \''; $io },
  0            
64 0     0     'psgi.errors' => io_from_write_cb sub { $request->print_stderr(@_) },
65 0 0 0       'psgi.multithread' => 0,
66             'psgi.multiprocess' => 0,
67             'psgi.run_once' => 0,
68             'psgi.streaming' => 1,
69             'psgi.nonblocking' => 1,
70             'psgix.input.buffered' => 1,
71             };
72              
73 0           my $res = Plack::Util::run_app($app, $env);
74              
75 0 0         if (ref $res eq 'ARRAY') {
    0          
76 0           $self->handle_response($res, $request);
77             } elsif (ref $res eq 'CODE') {
78 0     0     $res->(sub { $self->handle_response($_[0], $request) });
  0            
79             } else {
80 0           die "Bad response: $res";
81             }
82             }
83              
84             sub handle_response {
85 0     0 0   my($self, $res, $request) = @_;
86              
87 0           my $hdrs;
88 0           $hdrs = "Status: $res->[0]\015\012";
89              
90 0           my $headers = $res->[1];
91 0           while (my ($k, $v) = splice @$headers, 0, 2) {
92 0           $hdrs .= "$k: $v\015\012";
93             }
94 0           $hdrs .= "\015\012";
95              
96 0           $request->print_stdout($hdrs);
97              
98 0     0     my $cb = sub { $request->print_stdout($_[0]) };
  0            
99 0           my $body = $res->[2];
100 0 0         if (defined $body) {
101 0           Plack::Util::foreach($body, $cb);
102 0           $request->finish;
103             } else {
104             return Plack::Util::inline_object
105             write => $cb,
106 0     0     close => sub { $request->finish };
  0            
107             }
108             }
109              
110              
111             1;
112             __END__