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