File Coverage

blib/lib/CGI/Fast.pm
Criterion Covered Total %
statement 54 54 100.0
branch 18 20 90.0
condition 33 41 80.4
subroutine 13 13 100.0
pod 1 3 33.3
total 119 131 90.8


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