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