IIS 6.0 FastCGI env patch from janus
[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         elsif ( $options->{detach} ) {
135             $self->daemon_detach();
136         }
137     }
138
139     while ( $request->Accept >= 0 ) {
140         $proc_manager && $proc_manager->pm_pre_dispatch();
141         
142         $self->_fix_env( \%env );
143         
144         $class->handle_request( env => \%env );
145         
146         $proc_manager && $proc_manager->pm_post_dispatch();
147     }
148 }
149
150 =head2 $self->write($c, $buffer)
151
152 =cut
153
154 sub write {
155     my ( $self, $c, $buffer ) = @_;
156
157     unless ( $self->_prepared_write ) {
158         $self->prepare_write($c);
159         $self->_prepared_write(1);
160     }
161     
162     # XXX: We can't use Engine's write() method because syswrite
163     # appears to return bogus values instead of the number of bytes
164     # written: http://www.fastcgi.com/om_archive/mail-archive/0128.html
165     
166     # Prepend the headers if they have not yet been sent
167     if ( $self->_has_header_buf ) {
168         $buffer = $self->_clear_header_buf . $buffer;
169     }
170
171     # FastCGI does not stream data properly if using 'print $handle',
172     # but a syswrite appears to work properly.
173     *STDOUT->syswrite($buffer);
174 }
175
176 =head2 $self->daemon_fork()
177
178 Performs the first part of daemon initialisation.  Specifically,
179 forking.  STDERR, etc are still connected to a terminal.
180
181 =cut
182
183 sub daemon_fork {
184     require POSIX;
185     fork && exit;
186 }
187
188 =head2 $self->daemon_detach( )
189
190 Performs the second part of daemon initialisation.  Specifically,
191 disassociates from the terminal.
192
193 However, this does B<not> change the current working directory to "/",
194 as normal daemons do.  It also does not close all open file
195 descriptors (except STDIN, STDOUT and STDERR, which are re-opened from
196 F</dev/null>).
197
198 =cut
199
200 sub daemon_detach {
201     my $self = shift;
202     print "FastCGI daemon started (pid $$)\n";
203     open STDIN,  "+</dev/null" or die $!;
204     open STDOUT, ">&STDIN"     or die $!;
205     open STDERR, ">&STDIN"     or die $!;
206     POSIX::setsid();
207 }
208
209 =head2 $self->_fix_env( $env )
210
211 Adjusts the environment variables when necessary.
212
213 =cut
214
215 sub _fix_env
216 {
217     my $self = shift;
218     my $env = shift;
219
220     return unless ( $env->{SERVER_SOFTWARE} );
221
222     # If we're running under Lighttpd, swap PATH_INFO and SCRIPT_NAME
223     # http://lists.scsys.co.uk/pipermail/catalyst/2006-June/008361.html
224     # Thanks to Mark Blythe for this fix
225     if ( $env->{SERVER_SOFTWARE} =~ /lighttpd/ ) {
226         $env->{PATH_INFO} ||= delete $env->{SCRIPT_NAME};
227     }
228     # Fix the environment variables PATH_INFO and SCRIPT_NAME when running under IIS 6.0
229     elsif ( $env->{SERVER_SOFTWARE} =~ /IIS\/6.0/ ) {
230         my @script_name = split(m!/!, $env->{PATH_INFO});
231         my @path_translated = split(m!/|\\\\?!, $env->{PATH_TRANSLATED});
232         my @path_info;
233
234         while ($script_name[$#script_name] eq $path_translated[$#path_translated]) {
235             pop(@path_translated);
236             unshift(@path_info, pop(@script_name));
237         }
238
239         unshift(@path_info, '', '');
240
241         $env->{PATH_INFO} = join('/', @path_info);
242         $env->{SCRIPT_NAME} = join('/', @script_name);
243     }
244 }
245
246 1;
247 __END__
248
249 =head1 WEB SERVER CONFIGURATIONS
250
251 =head2 Standalone FastCGI Server
252
253 In server mode the application runs as a standalone server and accepts 
254 connections from a web server.  The application can be on the same machine as
255 the web server, on a remote machine, or even on multiple remote machines.
256 Advantages of this method include running the Catalyst application as a
257 different user than the web server, and the ability to set up a scalable
258 server farm.
259
260 To start your application in server mode, install the FCGI::ProcManager
261 module and then use the included fastcgi.pl script.
262
263     $ script/myapp_fastcgi.pl -l /tmp/myapp.socket -n 5
264     
265 Command line options for fastcgi.pl include:
266
267     -d -daemon     Daemonize the server.
268     -p -pidfile    Write a pidfile with the pid of the process manager.
269     -l -listen     Listen on a socket path, hostname:port, or :port.
270     -n -nproc      The number of processes started to handle requests.
271     
272 See below for the specific web server configurations for using the external
273 server.
274
275 =head2 Apache 1.x, 2.x
276
277 Apache requires the mod_fastcgi module.  The same module supports both
278 Apache 1 and 2.
279
280 There are three ways to run your application under FastCGI on Apache: server, 
281 static, and dynamic.
282
283 =head3 Standalone server mode
284
285     FastCgiExternalServer /tmp/myapp.fcgi -socket /tmp/myapp.socket
286     Alias /myapp/ /tmp/myapp/myapp.fcgi/
287     
288     # Or, run at the root
289     Alias / /tmp/myapp.fcgi/
290     
291     # Optionally, rewrite the path when accessed without a trailing slash
292     RewriteRule ^/myapp$ myapp/ [R]
293     
294
295 The FastCgiExternalServer directive tells Apache that when serving
296 /tmp/myapp to use the FastCGI application listenting on the socket
297 /tmp/mapp.socket.  Note that /tmp/myapp.fcgi does not need to exist --
298 it's a virtual file name.  With some versions of C<mod_fastcgi> or
299 C<mod_fcgid>, you can use any name you like, but most require that the
300 virtual filename end in C<.fcgi>.
301
302 It's likely that Apache is not configured to serve files in /tmp, so the 
303 Alias directive maps the url path /myapp/ to the (virtual) file that runs the
304 FastCGI application. The trailing slashes are important as their use will
305 correctly set the PATH_INFO environment variable used by Catalyst to
306 determine the request path.  If you would like to be able to access your app
307 without a trailing slash (http://server/myapp), you can use the above
308 RewriteRule directive.
309
310 =head3 Static mode
311
312 The term 'static' is misleading, but in static mode Apache uses its own
313 FastCGI Process Manager to start the application processes.  This happens at
314 Apache startup time.  In this case you do not run your application's
315 fastcgi.pl script -- that is done by Apache. Apache then maps URIs to the
316 FastCGI script to run your application.
317
318     FastCgiServer /path/to/myapp/script/myapp_fastcgi.pl -processes 3
319     Alias /myapp/ /path/to/myapp/script/myapp_fastcgi.pl/
320     
321 FastCgiServer tells Apache to start three processes of your application at
322 startup.  The Alias command maps a path to the FastCGI application. Again,
323 the trailing slashes are important.
324     
325 =head3 Dynamic mode
326
327 In FastCGI dynamic mode, Apache will run your application on demand, 
328 typically by requesting a file with a specific extension (e.g. .fcgi).  ISPs
329 often use this type of setup to provide FastCGI support to many customers.
330
331 In this mode it is often enough to place or link your *_fastcgi.pl script in
332 your cgi-bin directory with the extension of .fcgi.  In dynamic mode Apache
333 must be able to run your application as a CGI script so ExecCGI must be
334 enabled for the directory.
335
336     AddHandler fastcgi-script .fcgi
337
338 The above tells Apache to run any .fcgi file as a FastCGI application.
339
340 Here is a complete example:
341
342     <VirtualHost *:80>
343         ServerName www.myapp.com
344         DocumentRoot /path/to/MyApp
345
346         # Allow CGI script to run
347         <Directory /path/to/MyApp>
348             Options +ExecCGI
349         </Directory>
350
351         # Tell Apache this is a FastCGI application
352         <Files myapp_fastcgi.pl>
353             SetHandler fastcgi-script
354         </Files>
355     </VirtualHost>
356
357 Then a request for /script/myapp_fastcgi.pl will run the
358 application.
359     
360 For more information on using FastCGI under Apache, visit
361 L<http://www.fastcgi.com/mod_fastcgi/docs/mod_fastcgi.html>
362
363 =head3 Authorization header with mod_fastcgi or mod_cgi
364
365 By default, mod_fastcgi/mod_cgi do not pass along the Authorization header,
366 so modules like C<Catalyst::Plugin::Authentication::Credential::HTTP> will
367 not work.  To enable pass-through of this header, add the following
368 mod_rewrite directives:
369
370     RewriteCond %{HTTP:Authorization} ^(.+)
371     RewriteRule ^(.*)$ $1 [E=HTTP_AUTHORIZATION:%1,PT]
372
373 =head2 Lighttpd
374
375 These configurations were tested with Lighttpd 1.4.7.
376
377 =head3 Standalone server mode
378
379     server.document-root = "/var/www/MyApp/root"
380
381     fastcgi.server = (
382         "" => (
383             "MyApp" => (
384                 "socket"      => "/tmp/myapp.socket",
385                 "check-local" => "disable"
386             )
387         )
388     )
389
390 =head3 Static mode
391
392     server.document-root = "/var/www/MyApp/root"
393     
394     fastcgi.server = (
395         "" => (
396             "MyApp" => (
397                 "socket"       => "/tmp/myapp.socket",
398                 "check-local"  => "disable",
399                 "bin-path"     => "/var/www/MyApp/script/myapp_fastcgi.pl",
400                 "min-procs"    => 2,
401                 "max-procs"    => 5,
402                 "idle-timeout" => 20
403             )
404         )
405     )
406     
407 Note that in newer versions of lighttpd, the min-procs and idle-timeout
408 values are disabled.  The above example would start 5 processes.
409
410 =head3 Non-root configuration
411     
412 You can also run your application at any non-root location with either of the
413 above modes.  Note the required mod_rewrite rule.
414
415     url.rewrite = ( "myapp\$" => "myapp/" )
416     fastcgi.server = (
417         "/myapp" => (
418             "MyApp" => (
419                 # same as above
420             )
421         )
422     )
423
424 For more information on using FastCGI under Lighttpd, visit
425 L<http://www.lighttpd.net/documentation/fastcgi.html>
426
427 =head2 IIS
428
429 It is possible to run Catalyst under IIS with FastCGI, but we do not
430 yet have detailed instructions.
431
432 =head1 SEE ALSO
433
434 L<Catalyst>, L<FCGI>.
435
436 =head1 AUTHORS
437
438 Catalyst Contributors, see Catalyst.pm
439
440 =head1 THANKS
441
442 Bill Moseley, for documentation updates and testing.
443
444 =head1 COPYRIGHT
445
446 This program is free software, you can redistribute it and/or modify it under
447 the same terms as Perl itself.
448
449 =cut