File Coverage

blib/lib/Net/Async/FastCGI/PSGI.pm
Criterion Covered Total %
statement 43 43 100.0
branch 12 16 75.0
condition 1 2 50.0
subroutine 7 7 100.0
pod 2 2 100.0
total 65 70 92.8


line stmt bran cond sub pod time code
1             # You may distribute under the terms of either the GNU General Public License
2             # or the Artistic License (the same terms as Perl itself)
3             #
4             # (C) Paul Evans, 2010-2024 -- leonerd@leonerd.org.uk
5              
6             package Net::Async::FastCGI::PSGI 0.26;
7              
8 2     2   657077 use v5.14;
  2         9  
9 2     2   31 use warnings;
  2         12  
  2         148  
10              
11 2     2   14 use Carp;
  2         12  
  2         171  
12              
13 2     2   12 use base qw( Net::Async::FastCGI );
  2         6  
  2         1172  
14              
15             my $CRLF = "\x0d\x0a";
16              
17             =head1 NAME
18              
19             C - use C applications with C
20              
21             =head1 SYNOPSIS
22              
23             use Net::Async::FastCGI::PSGI;
24             use IO::Async::Loop;
25              
26             my $loop = IO::Async::Loop->new;
27              
28             my $fcgi = Net::Async::FastCGI::PSGI->new(
29             port => 12345,
30             app => sub {
31             my $env = shift;
32              
33             return [
34             200,
35             [ "Content-Type" => "text/plain" ],
36             [ "Hello, world!" ],
37             ];
38             },
39             );
40              
41             $loop->add( $fcgi );
42              
43             $loop->run;
44              
45             =head1 DESCRIPTION
46              
47             This subclass of L allows a FastCGI responder to use a
48             L application to respond to requests. It acts as a gateway between the
49             FastCGI connection from the webserver, and the C application. Aside from
50             the use of C instead of the C event, this class behaves
51             similarly to C.
52              
53             =cut
54              
55             =head1 PARAMETERS
56              
57             The following named parameters may be passed to C or C:
58              
59             =over 8
60              
61             =item app => CODE
62              
63             Reference to the actual C application to use for responding to requests
64              
65             =back
66              
67             =cut
68              
69             sub configure
70             {
71 5     5 1 15041 my $self = shift;
72 5         28 my %args = @_;
73              
74 5 50       78 if( exists $args{app} ) {
75 5         50 $self->{app} = delete $args{app};
76             }
77              
78 5         40 $self->SUPER::configure( %args );
79             }
80              
81             =head1 PSGI ENVIRONMENT
82              
83             The following extra keys are supplied to the environment of the C app:
84              
85             =over 8
86              
87             =item C
88              
89             The C object serving the request
90              
91             =item C
92              
93             The L object representing this particular
94             request
95              
96             =item C
97              
98             The L object that the C object is
99             a member of.
100              
101             =back
102              
103             =cut
104              
105             sub on_request
106             {
107 6     6 1 161 my $self = shift;
108 6         17 my ( $req ) = @_;
109              
110             # Much of this code stolen fro^W^Winspired by Plack::Handler::Net::FastCGI
111              
112             my %env = (
113 6 50 50     20 %{ $req->params },
  6         26  
114             'psgi.version' => [1,0],
115             'psgi.url_scheme' => ($req->param("HTTPS")||"off") =~ m/^(?:on|1)/i ? "https" : "http",
116             'psgi.input' => $req->stdin,
117             'psgi.errors' => $req->stderr,
118             'psgi.multithread' => 0,
119             'psgi.multiprocess' => 0,
120             'psgi.run_once' => 0,
121             'psgi.nonblocking' => 1,
122             'psgi.streaming' => 1,
123              
124             # Extensions
125             'net.async.fastcgi' => $self,
126             'net.async.fastcgi.req' => $req,
127             'io.async.loop' => $self->get_loop,
128             );
129              
130 6         222 my $resp = $self->{app}->( \%env );
131              
132             my $responder = sub {
133 6     6   6441 my ( $status, $headers, $body ) = @{ +shift };
  6         18  
134              
135 6         45 $req->print_stdout( "Status: $status$CRLF" );
136 6         2194 while( my ( $header, $value ) = splice @$headers, 0, 2 ) {
137 6         34 $req->print_stdout( "$header: $value$CRLF" );
138             }
139 6         21 $req->print_stdout( $CRLF );
140              
141 6 100       19 if( !defined $body ) {
142 1 50       3 croak "Responder given no body in void context" unless defined wantarray;
143              
144 1         4 return $req->stdout_with_close;
145             }
146              
147 5 100       41 if( ref $body eq "ARRAY" ) {
148 4         20 $req->print_stdout( $_ ) for @$body;
149 4         31 $req->finish( 0 );
150             }
151             else {
152             $req->stream_stdout_then_finish(
153             sub {
154 2         31 local $/ = \8192;
155 2         51 my $buffer = $body->getline;
156 2 100       10 defined $buffer and return $buffer;
157              
158 1         15 $body->close;
159 1         13 return undef;
160             },
161 1         12 0
162             );
163             }
164 6         3118 };
165              
166 6 100       31 if( ref $resp eq "ARRAY" ) {
    50          
167 4         13 $responder->( $resp );
168             }
169             elsif( ref $resp eq "CODE" ) {
170 2         5 $resp->( $responder );
171             }
172             }
173              
174             =head1 SEE ALSO
175              
176             =over 4
177              
178             =item *
179              
180             L - Perl Web Server Gateway Interface Specification
181              
182             =item *
183              
184             L - FastCGI handler for Plack using L
185              
186             =back
187              
188             =head1 AUTHOR
189              
190             Paul Evans
191              
192             =cut
193              
194             0x55AA;