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