package Plack::App::CGIBin; use strict; use warnings; use parent qw/Plack::App::File/; use Plack::Util::Accessor qw( exec_cb ); use Plack::App::WrapCGI; sub allow_path_info { 1 } my %exec_cache; sub would_exec { my($self, $file) = @_; return $exec_cache{$file} if exists $exec_cache{$file}; my $exec_cb = $self->exec_cb || sub { $self->exec_cb_default(@_) }; return $exec_cache{$file} = $exec_cb->($file); } sub exec_cb_default { my($self, $file) = @_; if ($file =~ /\.pl$/i) { return 0; } elsif ($self->shebang_for($file) =~ /^\#\!.*perl/) { return 0; } else { return 1; } } sub shebang_for { my($self, $file) = @_; open my $fh, "<", $file or return ''; my $line = <$fh>; return $line; } sub serve_path { my($self, $env, $file) = @_; local @{$env}{qw(SCRIPT_NAME PATH_INFO)} = @{$env}{qw( plack.file.SCRIPT_NAME plack.file.PATH_INFO )}; my $app = $self->{_compiled}->{$file} ||= Plack::App::WrapCGI->new( script => $file, execute => $self->would_exec($file), )->to_app; $app->($env); } 1; __END__ =head1 NAME Plack::App::CGIBin - cgi-bin replacement for Plack servers =head1 SYNOPSIS use Plack::App::CGIBin; use Plack::Builder; my $app = Plack::App::CGIBin->new(root => "/path/to/cgi-bin")->to_app; builder { mount "/cgi-bin" => $app; }; # Or from the command line plackup -MPlack::App::CGIBin -e 'Plack::App::CGIBin->new(root => "/path/to/cgi-bin")->to_app' =head1 DESCRIPTION Plack::App::CGIBin allows you to load CGI scripts from a directory and convert them into a PSGI application. This would give you the extreme easiness when you have bunch of old CGI scripts that is loaded using I of Apache web server. =head1 HOW IT WORKS This application checks if a given file path is a perl script and if so, uses L to compile a CGI script into a sub (like L) and then run it as a persistent application using L. If the given file is not a perl script, it executes the script just like a normal CGI script with fork & exec. This is like a normal web server mode and no performance benefit is achieved. The default mechanism to determine if a given file is a Perl script is as follows: =over 4 =item * Check if the filename ends with C<.pl>. If yes, it is a Perl script. =item * Open the file and see if the shebang (first line of the file) contains the word C (like C<#!/usr/bin/perl>). If yes, it is a Perl script. =back You can customize this behavior by passing C callback, which takes a file path to its first argument. For example, if your perl-based CGI script uses lots of global variables and such and are not ready to run on a persistent environment, you can do: my $app = Plack::App::CGIBin->new( root => "/path/to/cgi-bin", exec_cb => sub { 1 }, )->to_app; to always force the execute option for any files. =head1 AUTHOR Tatsuhiko Miyagawa =head1 SEE ALSO L L L L See also L if you compile one CGI script into a PSGI application without serving CGI scripts from a directory, to remove overhead of filesystem lookups, etc. =cut