Fix undef warning in Engine::FastCGI
[catagits/Catalyst-Runtime.git] / lib / Catalyst / Engine / FastCGI.pm
1 package Catalyst::Engine::FastCGI;
2
3 use Moose;
4 extends 'Catalyst::Engine::CGI';
5
6 # eval { Class::MOP::load_class("FCGI") };
7 eval "use FCGI";
8 die "Unable to load the FCGI module, you may need to install it:\n$@\n" if $@;
9
10 =head1 NAME
11
12 Catalyst::Engine::FastCGI - FastCGI Engine
13
14 =head1 DESCRIPTION
15
16 This is the FastCGI engine.
17
18 =head1 OVERLOADED METHODS
19
20 This class overloads some methods from C<Catalyst::Engine::CGI>.
21
22 =head2 $self->run($c, $listen, { option => value, ... })
23
24 Starts the FastCGI server.  If C<$listen> is set, then it specifies a
25 location to listen for FastCGI requests;
26
27 =over 4
28
29 =item /path
30
31 listen via Unix sockets on /path
32
33 =item :port
34
35 listen via TCP on port on all interfaces
36
37 =item hostname:port
38
39 listen via TCP on port bound to hostname
40
41 =back
42
43 Options may also be specified;
44
45 =over 4
46
47 =item leave_umask
48
49 Set to 1 to disable setting umask to 0 for socket open
50
51 =item nointr
52
53 Do not allow the listener to be interrupted by Ctrl+C
54
55 =item nproc
56
57 Specify a number of processes for FCGI::ProcManager
58
59 =item pidfile
60
61 Specify a filename for the pid file
62
63 =item manager
64
65 Specify a FCGI::ProcManager sub-class
66
67 =item detach
68
69 Detach from console
70
71 =item keep_stderr
72
73 Send STDERR to STDOUT instead of the webserver
74
75 =back
76
77 =cut
78
79 sub run {
80     my ( $self, $class, $listen, $options ) = @_;
81
82     my $sock = 0;
83     if ($listen) {
84         my $old_umask = umask;
85         unless ( $options->{leave_umask} ) {
86             umask(0);
87         }
88         $sock = FCGI::OpenSocket( $listen, 100 )
89           or die "failed to open FastCGI socket; $!";
90         unless ( $options->{leave_umask} ) {
91             umask($old_umask);
92         }
93     }
94     elsif ( $^O ne 'MSWin32' ) {
95         -S STDIN
96           or die "STDIN is not a socket; specify a listen location";
97     }
98
99     $options ||= {};
100
101     my %env;
102     my $error = \*STDERR; # send STDERR to the web server
103        $error = \*STDOUT  # send STDERR to stdout (a logfile)
104          if $options->{keep_stderr}; # (if asked to)
105
106     my $request =
107       FCGI::Request( \*STDIN, \*STDOUT, $error, \%env, $sock,
108         ( $options->{nointr} ? 0 : &FCGI::FAIL_ACCEPT_ON_INTR ),
109       );
110
111     my $proc_manager;
112
113     if ($listen) {
114         $options->{manager} ||= "FCGI::ProcManager";
115         $options->{nproc}   ||= 1;
116         $options->{proc_title} ||= "perl-fcgi-pm [$class]";
117
118         $self->daemon_fork() if $options->{detach};
119
120         if ( $options->{manager} ) {
121             eval "use $options->{manager}; 1" or die $@;
122
123             $proc_manager = $options->{manager}->new(
124                 {
125                     n_processes => $options->{nproc},
126                     pid_fname   => $options->{pidfile},
127                     pm_title => $options->{proc_title},
128                 }
129             );
130
131             # detach *before* the ProcManager inits
132             $self->daemon_detach() if $options->{detach};
133
134             $proc_manager->pm_manage();
135
136             # Give each child its own RNG state.
137             srand;
138         }
139         elsif ( $options->{detach} ) {
140             $self->daemon_detach();
141         }
142     }
143
144     while ( $request->Accept >= 0 ) {
145         $proc_manager && $proc_manager->pm_pre_dispatch();
146
147         $self->_fix_env( \%env );
148
149         $class->handle_request( env => \%env );
150
151         $proc_manager && $proc_manager->pm_post_dispatch();
152     }
153 }
154
155 =head2 $self->write($c, $buffer)
156
157 =cut
158
159 sub write {
160     my ( $self, $c, $buffer ) = @_;
161
162     # ->write will be called once with the body, even in a redirect (and
163     # in that case, the body is undef)
164     $buffer = '' if !defined $buffer;
165
166     unless ( $self->_prepared_write ) {
167         $self->prepare_write($c);
168         $self->_prepared_write(1);
169     }
170
171     # XXX: We can't use Engine's write() method because syswrite
172     # appears to return bogus values instead of the number of bytes
173     # written: http://www.fastcgi.com/om_archive/mail-archive/0128.html
174
175     # Prepend the headers if they have not yet been sent
176     if ( $self->_has_header_buf ) {
177         $buffer = $self->_clear_header_buf . $buffer;
178     }
179
180     # FastCGI does not stream data properly if using 'print $handle',
181     # but a syswrite appears to work properly.
182     *STDOUT->syswrite($buffer);
183 }
184
185 =head2 $self->daemon_fork()
186
187 Performs the first part of daemon initialisation.  Specifically,
188 forking.  STDERR, etc are still connected to a terminal.
189
190 =cut
191
192 sub daemon_fork {
193     require POSIX;
194     fork && exit;
195 }
196
197 =head2 $self->daemon_detach( )
198
199 Performs the second part of daemon initialisation.  Specifically,
200 disassociates from the terminal.
201
202 However, this does B<not> change the current working directory to "/",
203 as normal daemons do.  It also does not close all open file
204 descriptors (except STDIN, STDOUT and STDERR, which are re-opened from
205 F</dev/null>).
206
207 =cut
208
209 sub daemon_detach {
210     my $self = shift;
211     print "FastCGI daemon started (pid $$)\n";
212     open STDIN,  "+</dev/null" or die $!;
213     open STDOUT, ">&STDIN"     or die $!;
214     open STDERR, ">&STDIN"     or die $!;
215     POSIX::setsid();
216 }
217
218 =head2 $self->_fix_env( $env )
219
220 Adjusts the environment variables when necessary.
221
222 =cut
223
224 sub _fix_env
225 {
226     my $self = shift;
227     my $env = shift;
228
229     # we are gonna add variables from current system environment %ENV to %env
230     # that contains at this moment just variables taken from FastCGI request
231     foreach my $k (keys(%ENV)) {
232       $env->{$k} = $ENV{$k} unless defined($env->{$k});
233     }
234
235     return unless ( $env->{SERVER_SOFTWARE} );
236
237     # If we're running under Lighttpd, swap PATH_INFO and SCRIPT_NAME
238     # http://lists.scsys.co.uk/pipermail/catalyst/2006-June/008361.html
239     # Thanks to Mark Blythe for this fix
240     if ( $env->{SERVER_SOFTWARE} =~ /lighttpd/ ) {
241         $env->{PATH_INFO} ||= delete $env->{SCRIPT_NAME};
242     }
243     elsif ( $env->{SERVER_SOFTWARE} =~ /^nginx/ ) {
244         my $script_name = $env->{SCRIPT_NAME};
245         $env->{PATH_INFO} =~ s/^$script_name//g;
246     }
247     # Fix the environment variables PATH_INFO and SCRIPT_NAME when running 
248     # under IIS
249     elsif ( $env->{SERVER_SOFTWARE} =~ /IIS\/[6-9]\.[0-9]/ ) {
250         my @script_name = split(m!/!, $env->{PATH_INFO});
251         my @path_translated = split(m!/|\\\\?!, $env->{PATH_TRANSLATED});
252         my @path_info;
253
254         while ($script_name[$#script_name] eq $path_translated[$#path_translated]) {
255             pop(@path_translated);
256             unshift(@path_info, pop(@script_name));
257         }
258
259         unshift(@path_info, '', '');
260
261         $env->{PATH_INFO} = join('/', @path_info);
262         $env->{SCRIPT_NAME} = join('/', @script_name);
263     }
264 }
265
266 1;
267 __END__
268
269 =head1 WEB SERVER CONFIGURATIONS
270
271 =head2 Standalone FastCGI Server
272
273 In server mode the application runs as a standalone server and accepts
274 connections from a web server.  The application can be on the same machine as
275 the web server, on a remote machine, or even on multiple remote machines.
276 Advantages of this method include running the Catalyst application as a
277 different user than the web server, and the ability to set up a scalable
278 server farm.
279
280 To start your application in server mode, install the FCGI::ProcManager
281 module and then use the included fastcgi.pl script.
282
283     $ script/myapp_fastcgi.pl -l /tmp/myapp.socket -n 5
284
285 Command line options for fastcgi.pl include:
286
287     -d -daemon     Daemonize the server.
288     -p -pidfile    Write a pidfile with the pid of the process manager.
289     -l -listen     Listen on a socket path, hostname:port, or :port.
290     -n -nproc      The number of processes started to handle requests.
291
292 See below for the specific web server configurations for using the external
293 server.
294
295 =head2 Apache 1.x, 2.x
296
297 Apache requires the mod_fastcgi module.  The same module supports both
298 Apache 1 and 2.
299
300 There are three ways to run your application under FastCGI on Apache: server,
301 static, and dynamic.
302
303 =head3 Standalone server mode
304
305     FastCgiExternalServer /tmp/myapp.fcgi -socket /tmp/myapp.socket
306     Alias /myapp/ /tmp/myapp.fcgi/
307
308     # Or, run at the root
309     Alias / /tmp/myapp.fcgi/
310
311     # Optionally, rewrite the path when accessed without a trailing slash
312     RewriteRule ^/myapp$ myapp/ [R]
313
314
315 The FastCgiExternalServer directive tells Apache that when serving
316 /tmp/myapp to use the FastCGI application listenting on the socket
317 /tmp/mapp.socket.  Note that /tmp/myapp.fcgi B<MUST NOT> exist --
318 it's a virtual file name.  With some versions of C<mod_fastcgi> or
319 C<mod_fcgid>, you can use any name you like, but some require that the
320 virtual filename end in C<.fcgi>.
321
322 It's likely that Apache is not configured to serve files in /tmp, so the
323 Alias directive maps the url path /myapp/ to the (virtual) file that runs the
324 FastCGI application. The trailing slashes are important as their use will
325 correctly set the PATH_INFO environment variable used by Catalyst to
326 determine the request path.  If you would like to be able to access your app
327 without a trailing slash (http://server/myapp), you can use the above
328 RewriteRule directive.
329
330 =head3 Static mode
331
332 The term 'static' is misleading, but in static mode Apache uses its own
333 FastCGI Process Manager to start the application processes.  This happens at
334 Apache startup time.  In this case you do not run your application's
335 fastcgi.pl script -- that is done by Apache. Apache then maps URIs to the
336 FastCGI script to run your application.
337
338     FastCgiServer /path/to/myapp/script/myapp_fastcgi.pl -processes 3
339     Alias /myapp/ /path/to/myapp/script/myapp_fastcgi.pl/
340
341 FastCgiServer tells Apache to start three processes of your application at
342 startup.  The Alias command maps a path to the FastCGI application. Again,
343 the trailing slashes are important.
344
345 =head3 Dynamic mode
346
347 In FastCGI dynamic mode, Apache will run your application on demand,
348 typically by requesting a file with a specific extension (e.g. .fcgi).  ISPs
349 often use this type of setup to provide FastCGI support to many customers.
350
351 In this mode it is often enough to place or link your *_fastcgi.pl script in
352 your cgi-bin directory with the extension of .fcgi.  In dynamic mode Apache
353 must be able to run your application as a CGI script so ExecCGI must be
354 enabled for the directory.
355
356     AddHandler fastcgi-script .fcgi
357
358 The above tells Apache to run any .fcgi file as a FastCGI application.
359
360 Here is a complete example:
361
362     <VirtualHost *:80>
363         ServerName www.myapp.com
364         DocumentRoot /path/to/MyApp
365
366         # Allow CGI script to run
367         <Directory /path/to/MyApp>
368             Options +ExecCGI
369         </Directory>
370
371         # Tell Apache this is a FastCGI application
372         <Files myapp_fastcgi.pl>
373             SetHandler fastcgi-script
374         </Files>
375     </VirtualHost>
376
377 Then a request for /script/myapp_fastcgi.pl will run the
378 application.
379
380 For more information on using FastCGI under Apache, visit
381 L<http://www.fastcgi.com/mod_fastcgi/docs/mod_fastcgi.html>
382
383 =head3 Authorization header with mod_fastcgi or mod_cgi
384
385 By default, mod_fastcgi/mod_cgi do not pass along the Authorization header,
386 so modules like C<Catalyst::Plugin::Authentication::Credential::HTTP> will
387 not work.  To enable pass-through of this header, add the following
388 mod_rewrite directives:
389
390     RewriteCond %{HTTP:Authorization} ^(.+)
391     RewriteRule ^(.*)$ $1 [E=HTTP_AUTHORIZATION:%1,PT]
392
393 =head2 Lighttpd
394
395 These configurations were tested with Lighttpd 1.4.7.
396
397 =head3 Standalone server mode
398
399     server.document-root = "/var/www/MyApp/root"
400
401     fastcgi.server = (
402         "" => (
403             "MyApp" => (
404                 "socket"      => "/tmp/myapp.socket",
405                 "check-local" => "disable"
406             )
407         )
408     )
409
410 =head3 Static mode
411
412     server.document-root = "/var/www/MyApp/root"
413
414     fastcgi.server = (
415         "" => (
416             "MyApp" => (
417                 "socket"       => "/tmp/myapp.socket",
418                 "check-local"  => "disable",
419                 "bin-path"     => "/var/www/MyApp/script/myapp_fastcgi.pl",
420                 "min-procs"    => 2,
421                 "max-procs"    => 5,
422                 "idle-timeout" => 20
423             )
424         )
425     )
426
427 Note that in newer versions of lighttpd, the min-procs and idle-timeout
428 values are disabled.  The above example would start 5 processes.
429
430 =head3 Non-root configuration
431
432 You can also run your application at any non-root location with either of the
433 above modes.  Note the required mod_rewrite rule.
434
435     url.rewrite = ( "myapp\$" => "myapp/" )
436     fastcgi.server = (
437         "/myapp" => (
438             "MyApp" => (
439                 # same as above
440             )
441         )
442     )
443
444 For more information on using FastCGI under Lighttpd, visit
445 L<http://www.lighttpd.net/documentation/fastcgi.html>
446
447 =head2 nginx
448
449 Catalyst runs under nginx via FastCGI in a similar fashion as the lighttpd
450 standalone server as described above.
451
452 nginx does not have its own internal FastCGI process manager, so you must run
453 the FastCGI service separately.
454
455 =head3 Configuration
456
457 To configure nginx, you must configure the FastCGI parameters and also the
458 socket your FastCGI daemon is listening on.  It can be either a TCP socket
459 or a Unix file socket.
460
461 The server configuration block should look roughly like:
462
463     server {
464         listen $port;
465
466         location / {
467             fastcgi_param  QUERY_STRING       $query_string;
468             fastcgi_param  REQUEST_METHOD     $request_method;
469             fastcgi_param  CONTENT_TYPE       $content_type;
470             fastcgi_param  CONTENT_LENGTH     $content_length;
471
472             fastcgi_param  SCRIPT_NAME        /;
473             fastcgi_param  PATH_INFO          $fastcgi_script_name;
474             fastcgi_param  REQUEST_URI        $request_uri;
475             fastcgi_param  DOCUMENT_URI       $document_uri;
476             fastcgi_param  DOCUMENT_ROOT      $document_root;
477             fastcgi_param  SERVER_PROTOCOL    $server_protocol;
478
479             fastcgi_param  GATEWAY_INTERFACE  CGI/1.1;
480             fastcgi_param  SERVER_SOFTWARE    nginx/$nginx_version;
481
482             fastcgi_param  REMOTE_ADDR        $remote_addr;
483             fastcgi_param  REMOTE_PORT        $remote_port;
484             fastcgi_param  SERVER_ADDR        $server_addr;
485             fastcgi_param  SERVER_PORT        $server_port;
486             fastcgi_param  SERVER_NAME        $server_name;
487         
488             # Adjust the socket for your applications!
489             fastcgi_pass   unix:$docroot/myapp.socket;
490         }
491     }
492
493 It is the standard convention of nginx to include the fastcgi_params in a
494 separate file (usually something like C</etc/nginx/fastcgi_params>) and
495 simply include that file.
496
497 =head3  Non-root configuration
498
499 If you properly specify the PATH_INFO and SCRIPT_NAME parameters your
500 application will be accessible at any path. The SCRIPT_NAME variable is the
501 prefix of your application, and PATH_INFO would be everything in addition.
502
503 As an example, if your application is rooted at /myapp, you would configure:
504
505     fastcgi_param  SCRIPT_NAME /myapp/;
506     fastcgi_param  PATH_INFO   $fastcgi_script_name;
507
508 C<$fastcgi_script_name> would be "/myapp/path/of/the/action".  Catalyst will
509 process this accordingly and setup the application base as expected.
510
511 This behavior is somewhat different than Apache and Lighttpd, but is still
512 functional.
513
514 For more information on nginx, visit:
515 L<http://nginx.net>
516
517 =head2 Microsoft IIS
518
519 It is possible to run Catalyst under IIS with FastCGI, but only on IIS 6.0
520 (Microsoft Windows 2003), IIS 7.0 (Microsoft Windows 2008 and Vista) and
521 hopefully its successors.
522
523 Even if it is declared that FastCGI is supported on IIS 5.1 (Windows XP) it
524 does not support some features (specifically: wildcard mappings) that prevents
525 running Catalyst application.
526
527 Let us assume that our server has the following layout:
528
529     d:\WWW\WebApp\                   path to our Catalyst application
530     d:\strawberry\perl\bin\perl.exe  path to perl interpreter (with Catalyst installed)
531     c:\windows                       Windows directory
532
533 =head3 Setup IIS 6.0 (Windows 2003)
534
535 =over 4
536
537 =item Install FastCGI extension for IIS 6.0
538
539 FastCGI is not a standard part of IIS 6 - you have to install it separately. For
540 more info and download go to L<http://www.iis.net/extensions/FastCGI>. Choose
541 approptiate version (32-bit/64-bit), installation is quite simple
542 (in fact no questions, no options).
543
544 =item Create a new website
545
546 Open "Control Panel" > "Administrative Tools" > "Internet Information Services Manager".
547 Click "Action" > "New" > "Web Site". After you finish the installation wizard
548 you need to go to the new website's properties.
549
550 =item Set website properties
551
552 On tab "Web site" set proper values for:
553 Site Description, IP Address, TCP Port, SSL Port etc.
554
555 On tab "Home Directory" set the following:
556
557     Local path: "d:\WWW\WebApp\root"
558     Local path permission flags: check only "Read" + "Log visits"
559     Execute permitions: "Scripts only"
560
561 Click "Configuration" button (still on Home Directory tab) then click "Insert"
562 the wildcard application mapping and in the next dialog set:
563
564     Executable: "c:\windows\system32\inetsrv\fcgiext.dll"
565     Uncheck: "Verify that file exists"
566
567 Close all dialogs with "OK".
568
569 =item Edit fcgiext.ini
570
571 Put the following lines into c:\windows\system32\inetsrv\fcgiext.ini (on 64-bit
572 system c:\windows\syswow64\inetsrv\fcgiext.ini):
573
574     [Types]
575     *:8=CatalystApp
576     ;replace 8 with the identification number of the newly created website
577     ;it is not so easy to get this number:
578     ; - you can use utility "c:\inetpub\adminscripts\adsutil.vbs"
579     ;   to list websites:   "cscript adsutil.vbs ENUM /P /W3SVC"
580     ;   to get site name:   "cscript adsutil.vbs GET /W3SVC/<number>/ServerComment"
581     ;   to get all details: "cscript adsutil.vbs GET /W3SVC/<number>"
582     ; - or look where are the logs located:
583     ;   c:\WINDOWS\SYSTEM32\Logfiles\W3SVC7\whatever.log
584     ;   means that the corresponding number is "7"
585     ;if you are running just one website using FastCGI you can use '*=CatalystApp'
586
587     [CatalystApp]
588     ExePath=d:\strawberry\perl\bin\perl.exe
589     Arguments="d:\WWW\WebApp\script\webapp_fastcgi.pl -e"
590
591     ;by setting this you can instruct IIS to serve Catalyst static files
592     ;directly not via FastCGI (in case of any problems try 1)
593     IgnoreExistingFiles=0
594
595     ;do not be fooled by Microsoft doc talking about "IgnoreExistingDirectories"
596     ;that does not work and use "IgnoreDirectories" instead
597     IgnoreDirectories=1
598
599 =back
600
601 =head3 Setup IIS 7.0 (Windows 2008 and Vista)
602
603 Microsoft IIS 7.0 has built-in support for FastCGI so you do not have to install
604 any addons.
605
606 =over 4
607
608 =item Necessary steps during IIS7 installation
609
610 During IIS7 installation after you have added role "Web Server (IIS)"
611 you need to check to install role feature "CGI" (do not be nervous that it is
612 not FastCGI). If you already have IIS7 installed you can add "CGI" role feature
613 through "Control panel" > "Programs and Features".
614
615 =item Create a new website
616
617 Open "Control Panel" > "Administrative Tools" > "Internet Information Services Manager"
618 > "Add Web Site".
619
620     site name: "CatalystSite"
621     content directory: "d:\WWW\WebApp\root"
622     binding: set proper IP address, port etc.
623
624 =item Configure FastCGI
625
626 You can configure FastCGI extension using commandline utility
627 "c:\windows\system32\inetsrv\appcmd.exe"
628
629 =over 4
630
631 =item Configuring section "fastCgi" (it is a global setting)
632
633   appcmd.exe set config -section:system.webServer/fastCgi /+"[fullPath='d:\strawberry\perl\bin\perl.exe',arguments='d:\www\WebApp\script\webapp_fastcgi.pl -e',maxInstances='4',idleTimeout='300',activityTimeout='30',requestTimeout='90',instanceMaxRequests='1000',protocol='NamedPipe',flushNamedPipe='False']" /commit:apphost
634
635 =item Configuring proper handler (it is a site related setting)
636
637   appcmd.exe set config "CatalystSite" -section:system.webServer/handlers /+"[name='CatalystFastCGI',path='*',verb='GET,HEAD,POST',modules='FastCgiModule',scriptProcessor='d:\strawberry\perl\bin\perl.exe|d:\www\WebApp\script\webapp_fastcgi.pl -e',resourceType='Unspecified',requireAccess='Script']" /commit:apphost
638
639 Note: before launching the commands above do not forget to change site
640 name and paths to values relevant for your server setup.
641
642 =back
643
644 =back
645
646 =head1 SEE ALSO
647
648 L<Catalyst>, L<FCGI>.
649
650 =head1 AUTHORS
651
652 Catalyst Contributors, see Catalyst.pm
653
654 =head1 THANKS
655
656 Bill Moseley, for documentation updates and testing.
657
658 =head1 COPYRIGHT
659
660 This library is free software. You can redistribute it and/or modify it under
661 the same terms as Perl itself.
662
663 =cut