Plack-Handler-Net-FastCGI

 view release on metacpan or  search on metacpan

lib/Plack/Handler/Net/FastCGI.pm  view on Meta::CPAN

    my $socket;
    my $proto;
    my $port;

    if ($self->{listen}) {
        $port = $self->{listen}->[0];
        if ($port =~ s/^://) {
            $proto = 'tcp';
            $socket = IO::Socket::INET->new(
                Listen    => 5,
                LocalPort => $port,
                Reuse     => 1
            ) or die "Couldn't create listener socket: $!";
        } else {
            $proto = 'unix';
            $socket = IO::Socket::UNIX->new(
                Listen    => 5,
                Local     => $port,
            ) or die "Couldn't create UNIX listener socket: $!";
        }
    }
    else {
        (-S STDIN)
          || die "Standard input is not a socket: specify a listen location";

        $socket = \*STDIN;
        $proto  = 'tcp';

        if (HAS_AF_UNIX) {
            my $sockaddr = getsockname(*STDIN);
            if (unpack('S', $sockaddr)  == &Socket::AF_UNIX) {
                $proto = 'unix';
            }
        }
    }

    $self->{server_ready}->({
        host  => 'localhost',
        port  => $port,
        proto => $proto,
        server_software => 'Plack::Handler::Net::FastCGI',
    }) if $self->{server_ready} && $proto;

    while (accept(my $connection, $socket)) {
        $self->_handle_connection($connection);
    }
}

sub _handle_request {
    my($self, $env, $stdin, $stdout, $stderr) = @_;

    $env = {
        %$env,
        'psgi.version'      => [1,1],
        'psgi.url_scheme'   => ($env->{HTTPS}||'off') =~ /^(?:on|1)$/i ? 'https' : 'http',
        'psgi.input'        => $stdin,
        'psgi.errors'       => $stderr,
        'psgi.multithread'  => Plack::Util::FALSE,
        'psgi.multiprocess' => Plack::Util::FALSE,
        'psgi.run_once'     => Plack::Util::FALSE,
        'psgi.streaming'    => Plack::Util::TRUE,
        'psgi.nonblocking'  => Plack::Util::FALSE,
    };

    delete $env->{HTTP_CONTENT_TYPE};
    delete $env->{HTTP_CONTENT_LENGTH};

    # lighttpd munges multiple slashes in PATH_INFO into one. Try recovering it
    my $uri = URI->new("http://localhost" .  $env->{REQUEST_URI});
    $env->{PATH_INFO} = uri_unescape($uri->path);
    $env->{PATH_INFO} =~ s/^\Q$env->{SCRIPT_NAME}\E//;

    # root access for mod_fastcgi
    if (!exists $env->{PATH_INFO}) {
        $env->{PATH_INFO} = '';
    }

    my $res = Plack::Util::run_app $self->{app}, $env;

    if (ref $res eq 'ARRAY') {
        $self->_handle_response($res, $stdout);
    } elsif (ref $res eq 'CODE') {
        $res->(sub {
            $self->_handle_response($_[0], $stdout);
        });
    } else {
        die "Bad response $res";
    }
}

sub _handle_response {
    my ($self, $res, $stdout) = @_;

    my $hdrs;
    $hdrs = "Status: $res->[0]\015\012";

    my $headers = $res->[1];
    while (my ($k, $v) = splice @$headers, 0, 2) {
        $hdrs .= "$k: $v\015\012";
    }
    $hdrs .= "\015\012";

    print {$stdout} $hdrs;

    my $cb = sub { print {$stdout} $_[0] };
    my $body = $res->[2];
    if (defined $body) {
        Plack::Util::foreach($body, $cb);
    }
    else {
        return Plack::Util::inline_object
            write => $cb,
            close => sub { };
    }
}

our $STDOUT_BUFFER_SIZE = 8192;
our $STDERR_BUFFER_SIZE = 0;

use warnings FATAL => 'Net::FastCGI::IO';



( run in 0.387 second using v1.01-cache-2.11-cpan-9581c071862 )