FastCGI has been integrated with Perl in two different ways:
The two approaches are compatible at the Perl source code level; a Perl application developed using one approach can be run using the other. And both approaches result in a general-purpose Perl interpreter, not a Perl interpreter that's only usable for FastCGI applications.
This memo documents both approaches and explains a small Perl FastCGI application.
Perl interpreters incorporating sfio are not widely available in binary form, so most likely you'll have to build your own. Your build should go smoothly if you follow the instructions below. The instructions assume:
Follow these steps to build a Perl with sfio:
% cd $perl % ./Configure -Duseperlio -Dusesfio % make % make test % make install
There are certain Configure questions that must be answered differently when building Perl with sfio:
% setenv PERL5LIB $INSTALL/lib:$INSTALL/lib/sun4-solaris/perl5.003_02
% cd $sfiomod % $INSTALL/bin/perl Makefile.PL % make % make test % make install
If those are valid assumptions, follow these steps:
There are good sources of information on Perl at:
> cd $perl > mv perl.c perl.c.orig > mv proto.h proto.h.orig > mv Configure Configure.orig > cp -r ../fcgi-devel-kit/perl-5/perl5.002/* . > cp -r ../fcgi-devel-kit/perl-5/common/* .
The files you are copying contain the Perl-5 FCGI extension, some files modified from the distribution, and a script to simplify the configuration process.
> setenv FCGIDIR $fcgiIf you do not want to use gcc to build Perl you can set the environment variable CC to the desired compiler. For example:
> setenv CC gcc2.7By default Perl's installation prefix is /usr/local, so binaries get installed in /usr/local/bin, library files get installed into /usr/local/lib/perl, etc. If you want to specify a different installation prefix set the environment variable PERL_PREFIX.
> setenv PERL_PREFIX /usr/local/perl5-fcgi
> ./fcgi-configure
fcgi-configure is a wrapper around Perl's Configure script. It sets some variables according the the value of some environment variables, and runs Perl's Configure script in such a way that it does not prompt the user for any input. 90% of the time this should work without a problem. If for some reason this does not work for you, you'll have to follow the steps in the next section.
> make
> make install
> cd $perl > ./Configure
The file proto.h has some macros that conflict with the FastCGI macros. The version of proto.h supplied in the FastCGI kit includes these changes:
#ifdef _FCGI_STDIO #undef printf #endif
#ifdef _FCGI_STDIO #define printf FCGI_printf #endif
Perl-5.002 has a bug in perl.c that has a great chance of getting exercised with FastCGI. A fix has been sumbitted to the Perl developers and hopefully it'll make it into perl-5.003. It was a one line fix, here is a diff for the curious:
*** perl.c 1996/03/15 17:10:10 1.1 --- perl.c 1996/03/15 17:11:23 *************** *** 405,410 **** --- 405,411 ---- if (e_fp) { if (Fflush(e_fp) || ferror(e_fp) || fclose(e_fp)) croak("Can't write to temp file for -e: %s", Strerror(errno)); + e_fp = Nullfp; argc++,argv--; scriptname = e_tmpname; }Pretty straightforward.
> make [...] > make install
If you already have a Perl-5 package that has been configured, and you do not really want to re-run Configure, you can take the following steps.
THIS IS NOT RECOMMENDED
Edit config.sh with your favorite editor and modify the following lines:
One you have edited config.sh you should do a "make Makefile depend all". If you're paranoid like me you may want to do a "make clean" first.
The Perl program examples/tiny-perl-fcgi performs the same function as the C program examples/tiny-fcgi that's used as an example in the FastCGI Developer's Kit document. Here's what the Perl version looks like:
#!./perl use FCGI; $count = 0; while(FCGI::accept() >= 0) { print("Content-type: text/html\r\n\r\n", "<title>FastCGI Hello! (Perl)</title>\n", "<h1>FastCGI Hello! (Perl)</h1>\n", "Request number ", $++count, " running on host <i>$ENV('SERVER_NAME')</i>"); }If you've built Perl according to the recipe and you have a Web server set up to run FastCGI applications, load the FastCGI Developer's Kit Index Page in that server and run this Perl application now.
The script invokes Perl indirectly via the symbolic link examples/perl. It does this because HP-UX has a limit of 32 characters for the first line of a command-interpreter file such as examples/tiny-perl-fcgi. If you run on HP-UX you won't want to sprinkle symbolic links to perl everywhere, so you should choose a PERL_PREFIX shorter than /usr/local/perl5-fcgi.
You need to be aware of the following bug. If the initial environment to a FastCGI Perl application is empty (contains no name-value pairs) then when the first call to FCGI::accept returns, the environment will still be empty, i.e. %ENV will contain no associations. All the variables associated with the first request are lost. There are two known workarounds:
The Perl subroutine FCGI::accept treats the initial environment differently than the C function FCGI_Accept. The first call to the C function FCGI_Accept replaces the initial environment with the environment of the first request. The first call to the Perl subroutine FCGI::accept adds the variable bindings of the first request to the bindings present in the initial environment. So when the first call to FCGI::accept returns, bindings from the initial environment are still there (unless, due to naming conflicts, some of them have been overwritten by the first request). The next call to FCGI::accept removes the bindings made on the previous call before adding a new set for the request just accepted, again preserving the initial environment.
The Perl FCGI module also includes subroutines FCGI::finish, FCGI::set_exit_status, and FCGI::start_filter_data that correspond to C functions in fcgi_stdio.h; see the manpages for full information.
Converting a Perl CGI application to FastCGI is not fundamentally different from converting a C CGI application. You separate the portion of the application that performs one-time initialization from the portion that performs per-request processing. You put the per-request processing into a loop controlled by FCGI::accept.