1package CGI::Fast;
2use strict;
3use warnings;
4use if $] >= 5.019, 'deprecate';
5
6$CGI::Fast::VERSION='2.16';
7
8use CGI;
9use CGI::Carp;
10use FCGI;
11# use vars works like "our", but is compatible with older Perls.
12use vars qw(
13    @ISA
14    $ignore
15);
16@ISA = ('CGI');
17
18# workaround for known bug in libfcgi
19while (($ignore) = each %ENV) { }
20
21# override the initialization behavior so that
22# state is NOT maintained between invocations
23sub save_request {
24    # no-op
25}
26
27# If ENV{FCGI_SOCKET_PATH} is specified, we maintain a FCGI Request handle
28# in this package variable.
29use vars qw($Ext_Request $socket $socket_perm $queue);
30
31sub import {
32    my ($package,@import) = @_;
33    # check imports for this class then pass on
34    # imports to SUPER class
35    for (my $i = 0; $i < scalar( @import ); $i++) {
36        if ( $import[$i] eq 'socket_path' ) {
37            $socket = $import[$i+1];
38        } elsif ( $import[$i] eq 'socket_perm' ) {
39            $socket_perm = $import[$i+1];
40        } elsif ( $import[$i] eq 'listen_queue' ) {
41            $queue = $import[$i+1];
42        }
43    }
44    $package->SUPER::import(@import);
45}
46
47sub _create_fcgi_request {
48    my ( $in_fh,$out_fh,$err_fh ) = @_;
49    # If we have a socket set, explicitly open it
50    if ($ENV{FCGI_SOCKET_PATH} or $socket) {
51        my $path    = $ENV{FCGI_SOCKET_PATH}  || $socket;
52        my $perm    = $ENV{FCGI_SOCKET_PERM}  || $socket_perm;
53        my $backlog = $ENV{FCGI_LISTEN_QUEUE} || $queue || 100;
54        my $socket  = FCGI::OpenSocket( $path, $backlog );
55        if ($path !~ /^:/ && defined $perm) {
56            chmod $perm, $path or croak( "Couldn't chmod($path): $!" );
57        }
58        return FCGI::Request(
59            ( $in_fh  || \*STDIN ),
60            ( $out_fh || \*STDOUT ),
61            ( $err_fh || \*STDERR ),
62            \%ENV,
63            $socket,
64            1
65        );
66    }
67    else {
68        return FCGI::Request(
69            ( $in_fh  || \*STDIN ),
70            ( $out_fh || \*STDOUT ),
71            ( $err_fh || \*STDERR ),
72        );
73    }
74}
75
76{
77    my ( $in_fh,$out_fh,$err_fh );
78
79    sub file_handles {
80        my ($self, $handles) = @_;
81
82        if ( ref( $handles ) eq 'HASH' ) {
83            $in_fh  = delete( $handles->{fcgi_input_file_handle} );
84            $out_fh = delete( $handles->{fcgi_output_file_handle} );
85            $err_fh = delete( $handles->{fcgi_error_file_handle} );
86        }
87    }
88
89    sub new {
90
91		#
92		# the interface to the ->new method is unfortunately somewhat
93		# overloaded as it can be passed:
94		#
95		#         nothing
96		#         an upload hook, "something", 0
97		#         an initializer, an upload hook, "something", 0
98		#
99		# these then get passed through to the SUPER class (CGI.pm) that
100		# also has a constructor that can take various order of args
101		#
102        my ($self, @args) = @_;
103
104        if (
105			! $args[0]
106			|| (
107				ref( $args[0] )
108				&& UNIVERSAL::isa( $args[0],'CODE' )
109				&& ! $args[3]
110			)
111		) {
112            $Ext_Request ||= _create_fcgi_request( $in_fh,$out_fh,$err_fh );
113			my $accept = $Ext_Request->Accept;
114            return undef unless ( defined $accept && $accept >= 0 );
115        }
116        CGI->_reset_globals;
117        $self->_setup_symbols(@CGI::SAVED_SYMBOLS) if @CGI::SAVED_SYMBOLS;
118        return $CGI::Q = $self->SUPER::new(@args);
119    }
120}
121
1221;
123
124=head1 NAME
125
126CGI::Fast - CGI Interface for Fast CGI
127
128=for html
129<a href='https://travis-ci.org/leejo/cgi-fast?branch=master'><img src='https://travis-ci.org/leejo/cgi-fast.svg?branch=master' alt='Build Status' /></a>
130<a href='https://coveralls.io/r/leejo/cgi-fast?branch=master'><img src='https://coveralls.io/repos/leejo/cgi-fast/badge.png?branch=master' alt='Coverage Status' /></a>
131
132=head1 SYNOPSIS
133
134    use CGI::Fast
135        socket_path  => '9000',
136        socket_perm  => 0777,
137        listen_queue => 50;
138
139    use CGI qw/ :standard /;
140
141    $COUNTER = 0;
142
143    # optional, will default to STDOUT, STDERR
144    CGI::Fast->file_handles({
145        fcgi_output_file_handle => IO::Handle->new,
146        fcgi_error_file_handle  => IO::Handle->new,
147    });
148
149    while ($q = CGI::Fast->new) {
150        process_request($q);
151    }
152
153=head1 DESCRIPTION
154
155CGI::Fast is a subclass of the CGI object created by CGI.pm.  It is
156specialized to work with the FCGI module, which greatly speeds up CGI
157scripts by turning them into persistently running server processes.
158Scripts that perform time-consuming initialization processes, such as
159loading large modules or opening persistent database connections, will
160see large performance improvements.
161
162Note that as CGI::Fast is based on CGI.pm it is no longer advised as
163a way to write Perl web apps. See L<https://metacpan.org/pod/CGI#CGI.pm-HAS-BEEN-REMOVED-FROM-THE-PERL-CORE>
164for more information about this
165
166=head1 OTHER PIECES OF THE PUZZLE
167
168In order to use CGI::Fast you'll need the FCGI module.  See
169http://www.cpan.org/ for details.
170
171=head1 WRITING FASTCGI PERL SCRIPTS
172
173FastCGI scripts are persistent: one or more copies of the script
174are started up when the server initializes, and stay around until
175the server exits or they die a natural death.  After performing
176whatever one-time initialization it needs, the script enters a
177loop waiting for incoming connections, processing the request, and
178waiting some more.
179
180A typical FastCGI script will look like this:
181
182    #!perl
183    use CGI::Fast;
184    do_some_initialization();
185    while ($q = CGI::Fast->new) {
186        process_request($q);
187    }
188
189Each time there's a new request, CGI::Fast returns a
190CGI object to your loop.  The rest of the time your script
191waits in the call to new().  When the server requests that
192your script be terminated, new() will return undef.  You can
193of course exit earlier if you choose.  A new version of the
194script will be respawned to take its place (this may be
195necessary in order to avoid Perl memory leaks in long-running
196scripts).
197
198CGI.pm's default CGI object mode also works.  Just modify the loop
199this way:
200
201    while (CGI::Fast->new) {
202        process_request();
203    }
204
205Calls to header(), start_form(), etc. will all operate on the
206current request.
207
208=head1 INSTALLING FASTCGI SCRIPTS
209
210See the FastCGI developer's kit documentation for full details.  On
211the Apache server, the following line must be added to srm.conf:
212
213    AddType application/x-httpd-fcgi .fcgi
214
215FastCGI scripts must end in the extension .fcgi.  For each script you
216install, you must add something like the following to srm.conf:
217
218    FastCgiServer /usr/etc/httpd/fcgi-bin/file_upload.fcgi -processes 2
219
220This instructs Apache to launch two copies of file_upload.fcgi at
221startup time.
222
223=head1 USING FASTCGI SCRIPTS AS CGI SCRIPTS
224
225Any script that works correctly as a FastCGI script will also work
226correctly when installed as a vanilla CGI script.  However it will
227not see any performance benefit.
228
229=head1 EXTERNAL FASTCGI SERVER INVOCATION
230
231FastCGI supports a TCP/IP transport mechanism which allows FastCGI scripts to run
232external to the webserver, perhaps on a remote machine.  To configure the
233webserver to connect to an external FastCGI server, you would add the following
234to your srm.conf:
235
236    FastCgiExternalServer /usr/etc/httpd/fcgi-bin/file_upload.fcgi -host sputnik:8888
237
238Two environment variables affect how the C<CGI::Fast> object is created,
239allowing C<CGI::Fast> to be used as an external FastCGI server. (See C<FCGI>
240documentation for C<FCGI::OpenSocket> for more information.)
241
242You can set these as ENV variables or imports in the use CGI::Fast statement.
243If the ENV variables are set then these will be favoured so you can override
244the import statements on the command line, etc.
245
246=over
247
248=item FCGI_SOCKET_PATH / socket_path
249
250The address (TCP/IP) or path (UNIX Domain) of the socket the external FastCGI
251script to which bind an listen for incoming connections from the web server.
252
253=item FCGI_SOCKET_PERM / socket_perm
254
255Permissions for UNIX Domain socket.
256
257=item FCGI_LISTEN_QUEUE / listen_queue
258
259Maximum length of the queue of pending connections, defaults to 100.
260
261=back
262
263For example:
264
265    use CGI::Fast
266        socket_path  => "sputnik:8888",
267        listen_queue => "50"
268    ;
269
270    use CGI qw/ :standard /;
271
272    do_some_initialization();
273
274    while ($q = CGI::Fast->new) {
275        process_request($q);
276    }
277
278
279Or:
280
281    use CGI::Fast;
282    use CGI qw/ :standard /;
283
284    do_some_initialization();
285
286    $ENV{FCGI_SOCKET_PATH} = "sputnik:8888";
287    $ENV{FCGI_LISTEN_QUEUE} = 50;
288
289    while ($q = CGI::Fast->new) {
290        process_request($q);
291    }
292
293Note the importance of having use CGI after use CGI::Fast as this will
294prevent any CGI import pragmas being overwritten by CGI::Fast. You can
295use CGI::Fast as a drop in replacement like so:
296
297    use CGI::Fast qw/ :standard /
298
299=head1 FILE HANDLES
300
301FCGI defaults to using STDOUT and STDERR as its output filehandles - this
302may lead to unexpected redirect of output if you migrate scripts from CGI.pm
303to CGI::Fast. To get around this you can use the file_handles method, which
304you must do B<before> the first call to CGI::Fast->new. For example using
305IO::Handle:
306
307    CGI::Fast->file_handles({
308        fcgi_output_file_handle => IO::Handle->new,
309        fcgi_error_file_handle  => IO::Handle->new,
310    });
311
312    while (CGI::Fast->new) {
313        ..
314    }
315
316Overriding STDIN using the C<fcgi_input_file_handle> key is also possible,
317however doing so is likely to break at least POST requests.
318
319=head1 CAVEATS
320
321I haven't tested this very much.
322
323=head1 LICENSE
324
325Copyright 1996-1998, Lincoln D. Stein.  All rights reserved. Currently
326maintained by Lee Johnson
327
328This library is free software; you can redistribute it and/or modify
329it under the same terms as Perl itself.
330
331Address bug reports and comments to:
332
333    https://github.com/leejo/cgi-fast
334
335=head1 BUGS
336
337This section intentionally left blank.
338
339=head1 SEE ALSO
340
341L<CGI::Carp>, L<CGI>
342
343=cut
344