IIS 6.0 FastCGI env patch from janus
[catagits/Catalyst-Runtime.git] / lib / Catalyst / Engine / FastCGI.pm
CommitLineData
d1d9793f 1package Catalyst::Engine::FastCGI;
ffb41d94 2
7fa2c9c1 3use Moose;
4extends 'Catalyst::Engine::CGI';
5
0fc2d522 6# eval { Class::MOP::load_class("FCGI") };
6f409682 7eval "use FCGI";
500a1679 8die "Unable to load the FCGI module, you may need to install it:\n$@\n" if $@;
ffb41d94 9
10=head1 NAME
11
fbcc39ad 12Catalyst::Engine::FastCGI - FastCGI Engine
ffb41d94 13
14=head1 DESCRIPTION
15
fbcc39ad 16This is the FastCGI engine.
ffb41d94 17
e2fd5b5f 18=head1 OVERLOADED METHODS
19
fbcc39ad 20This class overloads some methods from C<Catalyst::Engine::CGI>.
e2fd5b5f 21
b5ecfcf0 22=head2 $self->run($c, $listen, { option => value, ... })
ac5c933b 23
5898abae 24Starts the FastCGI server. If C<$listen> is set, then it specifies a
25location to listen for FastCGI requests;
26
b799b493 27=over 4
28
29=item /path
30
31listen via Unix sockets on /path
32
33=item :port
34
35listen via TCP on port on all interfaces
36
37=item hostname:port
38
39listen via TCP on port bound to hostname
40
41=back
5898abae 42
43Options may also be specified;
44
b799b493 45=over 4
46
47=item leave_umask
48
88eee38e 49Set to 1 to disable setting umask to 0 for socket open
50
51=item nointr
b799b493 52
53Do not allow the listener to be interrupted by Ctrl+C
54
55=item nproc
56
57Specify a number of processes for FCGI::ProcManager
58
59=item pidfile
60
61Specify a filename for the pid file
62
63=item manager
64
65Specify a FCGI::ProcManager sub-class
66
ac5c933b 67=item detach
b799b493 68
69Detach from console
70
71=item keep_stderr
72
73Send STDERR to STDOUT instead of the webserver
74
75=back
e2fd5b5f 76
77=cut
78
fbcc39ad 79sub run {
5898abae 80 my ( $self, $class, $listen, $options ) = @_;
81
5db46287 82 my $sock = 0;
5898abae 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 }
6f2e0021 94 elsif ( $^O ne 'MSWin32' ) {
5898abae 95 -S STDIN
96 or die "STDIN is not a socket; specify a listen location";
97 }
98
99 $options ||= {};
6f409682 100
84528885 101 my %env;
6fc58422 102 my $error = \*STDERR; # send STDERR to the web server
103 $error = \*STDOUT # send STDERR to stdout (a logfile)
85d9fce6 104 if $options->{keep_stderr}; # (if asked to)
ac5c933b 105
5898abae 106 my $request =
6fc58422 107 FCGI::Request( \*STDIN, \*STDOUT, $error, \%env, $sock,
5898abae 108 ( $options->{nointr} ? 0 : &FCGI::FAIL_ACCEPT_ON_INTR ),
109 );
110
111 my $proc_manager;
6f409682 112
113 if ($listen) {
526b698a 114 $options->{manager} ||= "FCGI::ProcManager";
115 $options->{nproc} ||= 1;
b5ecfcf0 116
526b698a 117 $self->daemon_fork() if $options->{detach};
b5ecfcf0 118
526b698a 119 if ( $options->{manager} ) {
120 eval "use $options->{manager}; 1" or die $@;
121
b5ecfcf0 122 $proc_manager = $options->{manager}->new(
123 {
526b698a 124 n_processes => $options->{nproc},
125 pid_fname => $options->{pidfile},
b5ecfcf0 126 }
127 );
128
526b698a 129 # detach *before* the ProcManager inits
130 $self->daemon_detach() if $options->{detach};
131
132 $proc_manager->pm_manage();
dc2fc680 133 }
526b698a 134 elsif ( $options->{detach} ) {
135 $self->daemon_detach();
b5ecfcf0 136 }
5898abae 137 }
e2fd5b5f 138
fbcc39ad 139 while ( $request->Accept >= 0 ) {
5898abae 140 $proc_manager && $proc_manager->pm_pre_dispatch();
ac5c933b 141
c46dd4e8 142 $self->_fix_env( \%env );
ac5c933b 143
84528885 144 $class->handle_request( env => \%env );
ac5c933b 145
9f778270 146 $proc_manager && $proc_manager->pm_post_dispatch();
fbcc39ad 147 }
e2fd5b5f 148}
149
b5ecfcf0 150=head2 $self->write($c, $buffer)
e2fd5b5f 151
152=cut
153
fbcc39ad 154sub write {
155 my ( $self, $c, $buffer ) = @_;
4f5ebacd 156
02570318 157 unless ( $self->_prepared_write ) {
4f5ebacd 158 $self->prepare_write($c);
02570318 159 $self->_prepared_write(1);
fbcc39ad 160 }
ac5c933b 161
e512dd24 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
ac5c933b 165
e512dd24 166 # Prepend the headers if they have not yet been sent
02570318 167 if ( $self->_has_header_buf ) {
168 $buffer = $self->_clear_header_buf . $buffer;
e512dd24 169 }
4f5ebacd 170
fbcc39ad 171 # FastCGI does not stream data properly if using 'print $handle',
172 # but a syswrite appears to work properly.
4f5ebacd 173 *STDOUT->syswrite($buffer);
e2fd5b5f 174}
175
b5ecfcf0 176=head2 $self->daemon_fork()
526b698a 177
178Performs the first part of daemon initialisation. Specifically,
179forking. STDERR, etc are still connected to a terminal.
180
181=cut
182
183sub daemon_fork {
184 require POSIX;
185 fork && exit;
186}
187
b5ecfcf0 188=head2 $self->daemon_detach( )
526b698a 189
190Performs the second part of daemon initialisation. Specifically,
191disassociates from the terminal.
192
193However, this does B<not> change the current working directory to "/",
194as normal daemons do. It also does not close all open file
195descriptors (except STDIN, STDOUT and STDERR, which are re-opened from
196F</dev/null>).
197
198=cut
199
200sub daemon_detach {
201 my $self = shift;
202 print "FastCGI daemon started (pid $$)\n";
b5ecfcf0 203 open STDIN, "+</dev/null" or die $!;
204 open STDOUT, ">&STDIN" or die $!;
205 open STDERR, ">&STDIN" or die $!;
526b698a 206 POSIX::setsid();
207}
208
c46dd4e8 209=head2 $self->_fix_env( $env )
210
211Adjusts the environment variables when necessary.
212
213=cut
214
215sub _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
198b0efa 2461;
247__END__
248
198b0efa 249=head1 WEB SERVER CONFIGURATIONS
250
d7d72ad9 251=head2 Standalone FastCGI Server
252
ac5c933b 253In server mode the application runs as a standalone server and accepts
d7d72ad9 254connections from a web server. The application can be on the same machine as
255the web server, on a remote machine, or even on multiple remote machines.
256Advantages of this method include running the Catalyst application as a
257different user than the web server, and the ability to set up a scalable
258server farm.
198b0efa 259
d7d72ad9 260To start your application in server mode, install the FCGI::ProcManager
261module and then use the included fastcgi.pl script.
198b0efa 262
d7d72ad9 263 $ script/myapp_fastcgi.pl -l /tmp/myapp.socket -n 5
ac5c933b 264
d7d72ad9 265Command 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.
ac5c933b 271
d7d72ad9 272See below for the specific web server configurations for using the external
273server.
198b0efa 274
d7d72ad9 275=head2 Apache 1.x, 2.x
276
277Apache requires the mod_fastcgi module. The same module supports both
278Apache 1 and 2.
279
ac5c933b 280There are three ways to run your application under FastCGI on Apache: server,
d7d72ad9 281static, and dynamic.
282
283=head3 Standalone server mode
284
3f0911d3 285 FastCgiExternalServer /tmp/myapp.fcgi -socket /tmp/myapp.socket
286 Alias /myapp/ /tmp/myapp/myapp.fcgi/
ac5c933b 287
d7d72ad9 288 # Or, run at the root
3f0911d3 289 Alias / /tmp/myapp.fcgi/
ac5c933b 290
d7d72ad9 291 # Optionally, rewrite the path when accessed without a trailing slash
292 RewriteRule ^/myapp$ myapp/ [R]
ac5c933b 293
3f0911d3 294
295The 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 --
298it's a virtual file name. With some versions of C<mod_fastcgi> or
299C<mod_fcgid>, you can use any name you like, but most require that the
300virtual filename end in C<.fcgi>.
d7d72ad9 301
ac5c933b 302It's likely that Apache is not configured to serve files in /tmp, so the
d7d72ad9 303Alias directive maps the url path /myapp/ to the (virtual) file that runs the
304FastCGI application. The trailing slashes are important as their use will
305correctly set the PATH_INFO environment variable used by Catalyst to
306determine the request path. If you would like to be able to access your app
307without a trailing slash (http://server/myapp), you can use the above
308RewriteRule directive.
309
310=head3 Static mode
311
312The term 'static' is misleading, but in static mode Apache uses its own
313FastCGI Process Manager to start the application processes. This happens at
314Apache startup time. In this case you do not run your application's
315fastcgi.pl script -- that is done by Apache. Apache then maps URIs to the
316FastCGI 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/
ac5c933b 320
d7d72ad9 321FastCgiServer tells Apache to start three processes of your application at
322startup. The Alias command maps a path to the FastCGI application. Again,
323the trailing slashes are important.
ac5c933b 324
d7d72ad9 325=head3 Dynamic mode
326
ac5c933b 327In FastCGI dynamic mode, Apache will run your application on demand,
d7d72ad9 328typically by requesting a file with a specific extension (e.g. .fcgi). ISPs
329often use this type of setup to provide FastCGI support to many customers.
330
331In this mode it is often enough to place or link your *_fastcgi.pl script in
332your cgi-bin directory with the extension of .fcgi. In dynamic mode Apache
333must be able to run your application as a CGI script so ExecCGI must be
334enabled for the directory.
335
336 AddHandler fastcgi-script .fcgi
337
338The above tells Apache to run any .fcgi file as a FastCGI application.
339
340Here 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>
198b0efa 355 </VirtualHost>
d7d72ad9 356
357Then a request for /script/myapp_fastcgi.pl will run the
358application.
ac5c933b 359
198b0efa 360For more information on using FastCGI under Apache, visit
361L<http://www.fastcgi.com/mod_fastcgi/docs/mod_fastcgi.html>
362
25f55123 363=head3 Authorization header with mod_fastcgi or mod_cgi
364
365By default, mod_fastcgi/mod_cgi do not pass along the Authorization header,
366so modules like C<Catalyst::Plugin::Authentication::Credential::HTTP> will
367not work. To enable pass-through of this header, add the following
368mod_rewrite directives:
369
370 RewriteCond %{HTTP:Authorization} ^(.+)
371 RewriteRule ^(.*)$ $1 [E=HTTP_AUTHORIZATION:%1,PT]
372
198b0efa 373=head2 Lighttpd
374
d7d72ad9 375These 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
198b0efa 391
392 server.document-root = "/var/www/MyApp/root"
ac5c933b 393
198b0efa 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 )
ac5c933b 406
d7d72ad9 407Note that in newer versions of lighttpd, the min-procs and idle-timeout
408values are disabled. The above example would start 5 processes.
25810c41 409
d7d72ad9 410=head3 Non-root configuration
ac5c933b 411
d7d72ad9 412You can also run your application at any non-root location with either of the
2f381252 413above modes. Note the required mod_rewrite rule.
198b0efa 414
2f381252 415 url.rewrite = ( "myapp\$" => "myapp/" )
198b0efa 416 fastcgi.server = (
d7d72ad9 417 "/myapp" => (
198b0efa 418 "MyApp" => (
d7d72ad9 419 # same as above
198b0efa 420 )
421 )
422 )
423
424For more information on using FastCGI under Lighttpd, visit
425L<http://www.lighttpd.net/documentation/fastcgi.html>
426
427=head2 IIS
428
429It is possible to run Catalyst under IIS with FastCGI, but we do not
430yet have detailed instructions.
431
fbcc39ad 432=head1 SEE ALSO
e2fd5b5f 433
fbcc39ad 434L<Catalyst>, L<FCGI>.
cd3bb248 435
fbcc39ad 436=head1 AUTHORS
ffb41d94 437
2f381252 438Catalyst Contributors, see Catalyst.pm
ffb41d94 439
d7d72ad9 440=head1 THANKS
441
442Bill Moseley, for documentation updates and testing.
443
ffb41d94 444=head1 COPYRIGHT
445
446This program is free software, you can redistribute it and/or modify it under
447the same terms as Perl itself.
448
449=cut