mro compat stuff
[catagits/Catalyst-Runtime.git] / lib / Catalyst / Engine / FastCGI.pm
CommitLineData
d1d9793f 1package Catalyst::Engine::FastCGI;
ffb41d94 2
6f1f968a 3use MRO::Compat;
4use mro 'c3';
7fa2c9c1 5use Moose;
6extends 'Catalyst::Engine::CGI';
7
0fc2d522 8# eval { Class::MOP::load_class("FCGI") };
6f409682 9eval "use FCGI";
500a1679 10die "Unable to load the FCGI module, you may need to install it:\n$@\n" if $@;
ffb41d94 11
12=head1 NAME
13
fbcc39ad 14Catalyst::Engine::FastCGI - FastCGI Engine
ffb41d94 15
16=head1 DESCRIPTION
17
fbcc39ad 18This is the FastCGI engine.
ffb41d94 19
e2fd5b5f 20=head1 OVERLOADED METHODS
21
fbcc39ad 22This class overloads some methods from C<Catalyst::Engine::CGI>.
e2fd5b5f 23
b5ecfcf0 24=head2 $self->run($c, $listen, { option => value, ... })
ac5c933b 25
5898abae 26Starts the FastCGI server. If C<$listen> is set, then it specifies a
27location to listen for FastCGI requests;
28
b799b493 29=over 4
30
31=item /path
32
33listen via Unix sockets on /path
34
35=item :port
36
37listen via TCP on port on all interfaces
38
39=item hostname:port
40
41listen via TCP on port bound to hostname
42
43=back
5898abae 44
45Options may also be specified;
46
b799b493 47=over 4
48
49=item leave_umask
50
51Set to 1 to disable setting umask to 0 for socket open =item nointr
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
d7334071 142 # If we're running under Lighttpd, swap PATH_INFO and SCRIPT_NAME
143 # http://lists.rawmode.org/pipermail/catalyst/2006-June/008361.html
144 # Thanks to Mark Blythe for this fix
145 if ( $env{SERVER_SOFTWARE} && $env{SERVER_SOFTWARE} =~ /lighttpd/ ) {
3b6a7b7f 146 $env{PATH_INFO} ||= delete $env{SCRIPT_NAME};
d7334071 147 }
ac5c933b 148
84528885 149 $class->handle_request( env => \%env );
ac5c933b 150
9f778270 151 $proc_manager && $proc_manager->pm_post_dispatch();
fbcc39ad 152 }
e2fd5b5f 153}
154
b5ecfcf0 155=head2 $self->write($c, $buffer)
e2fd5b5f 156
157=cut
158
fbcc39ad 159sub write {
160 my ( $self, $c, $buffer ) = @_;
4f5ebacd 161
fbcc39ad 162 unless ( $self->{_prepared_write} ) {
4f5ebacd 163 $self->prepare_write($c);
fbcc39ad 164 $self->{_prepared_write} = 1;
165 }
ac5c933b 166
e512dd24 167 # XXX: We can't use Engine's write() method because syswrite
168 # appears to return bogus values instead of the number of bytes
169 # written: http://www.fastcgi.com/om_archive/mail-archive/0128.html
ac5c933b 170
e512dd24 171 # Prepend the headers if they have not yet been sent
172 if ( my $headers = delete $self->{_header_buf} ) {
173 $buffer = $headers . $buffer;
174 }
4f5ebacd 175
fbcc39ad 176 # FastCGI does not stream data properly if using 'print $handle',
177 # but a syswrite appears to work properly.
4f5ebacd 178 *STDOUT->syswrite($buffer);
e2fd5b5f 179}
180
b5ecfcf0 181=head2 $self->daemon_fork()
526b698a 182
183Performs the first part of daemon initialisation. Specifically,
184forking. STDERR, etc are still connected to a terminal.
185
186=cut
187
188sub daemon_fork {
189 require POSIX;
190 fork && exit;
191}
192
b5ecfcf0 193=head2 $self->daemon_detach( )
526b698a 194
195Performs the second part of daemon initialisation. Specifically,
196disassociates from the terminal.
197
198However, this does B<not> change the current working directory to "/",
199as normal daemons do. It also does not close all open file
200descriptors (except STDIN, STDOUT and STDERR, which are re-opened from
201F</dev/null>).
202
203=cut
204
205sub daemon_detach {
206 my $self = shift;
207 print "FastCGI daemon started (pid $$)\n";
b5ecfcf0 208 open STDIN, "+</dev/null" or die $!;
209 open STDOUT, ">&STDIN" or die $!;
210 open STDERR, ">&STDIN" or die $!;
526b698a 211 POSIX::setsid();
212}
213
198b0efa 2141;
215__END__
216
198b0efa 217=head1 WEB SERVER CONFIGURATIONS
218
d7d72ad9 219=head2 Standalone FastCGI Server
220
ac5c933b 221In server mode the application runs as a standalone server and accepts
d7d72ad9 222connections from a web server. The application can be on the same machine as
223the web server, on a remote machine, or even on multiple remote machines.
224Advantages of this method include running the Catalyst application as a
225different user than the web server, and the ability to set up a scalable
226server farm.
198b0efa 227
d7d72ad9 228To start your application in server mode, install the FCGI::ProcManager
229module and then use the included fastcgi.pl script.
198b0efa 230
d7d72ad9 231 $ script/myapp_fastcgi.pl -l /tmp/myapp.socket -n 5
ac5c933b 232
d7d72ad9 233Command line options for fastcgi.pl include:
234
235 -d -daemon Daemonize the server.
236 -p -pidfile Write a pidfile with the pid of the process manager.
237 -l -listen Listen on a socket path, hostname:port, or :port.
238 -n -nproc The number of processes started to handle requests.
ac5c933b 239
d7d72ad9 240See below for the specific web server configurations for using the external
241server.
198b0efa 242
d7d72ad9 243=head2 Apache 1.x, 2.x
244
245Apache requires the mod_fastcgi module. The same module supports both
246Apache 1 and 2.
247
ac5c933b 248There are three ways to run your application under FastCGI on Apache: server,
d7d72ad9 249static, and dynamic.
250
251=head3 Standalone server mode
252
3f0911d3 253 FastCgiExternalServer /tmp/myapp.fcgi -socket /tmp/myapp.socket
254 Alias /myapp/ /tmp/myapp/myapp.fcgi/
ac5c933b 255
d7d72ad9 256 # Or, run at the root
3f0911d3 257 Alias / /tmp/myapp.fcgi/
ac5c933b 258
d7d72ad9 259 # Optionally, rewrite the path when accessed without a trailing slash
260 RewriteRule ^/myapp$ myapp/ [R]
ac5c933b 261
3f0911d3 262
263The FastCgiExternalServer directive tells Apache that when serving
264/tmp/myapp to use the FastCGI application listenting on the socket
265/tmp/mapp.socket. Note that /tmp/myapp.fcgi does not need to exist --
266it's a virtual file name. With some versions of C<mod_fastcgi> or
267C<mod_fcgid>, you can use any name you like, but most require that the
268virtual filename end in C<.fcgi>.
d7d72ad9 269
ac5c933b 270It's likely that Apache is not configured to serve files in /tmp, so the
d7d72ad9 271Alias directive maps the url path /myapp/ to the (virtual) file that runs the
272FastCGI application. The trailing slashes are important as their use will
273correctly set the PATH_INFO environment variable used by Catalyst to
274determine the request path. If you would like to be able to access your app
275without a trailing slash (http://server/myapp), you can use the above
276RewriteRule directive.
277
278=head3 Static mode
279
280The term 'static' is misleading, but in static mode Apache uses its own
281FastCGI Process Manager to start the application processes. This happens at
282Apache startup time. In this case you do not run your application's
283fastcgi.pl script -- that is done by Apache. Apache then maps URIs to the
284FastCGI script to run your application.
285
286 FastCgiServer /path/to/myapp/script/myapp_fastcgi.pl -processes 3
287 Alias /myapp/ /path/to/myapp/script/myapp_fastcgi.pl/
ac5c933b 288
d7d72ad9 289FastCgiServer tells Apache to start three processes of your application at
290startup. The Alias command maps a path to the FastCGI application. Again,
291the trailing slashes are important.
ac5c933b 292
d7d72ad9 293=head3 Dynamic mode
294
ac5c933b 295In FastCGI dynamic mode, Apache will run your application on demand,
d7d72ad9 296typically by requesting a file with a specific extension (e.g. .fcgi). ISPs
297often use this type of setup to provide FastCGI support to many customers.
298
299In this mode it is often enough to place or link your *_fastcgi.pl script in
300your cgi-bin directory with the extension of .fcgi. In dynamic mode Apache
301must be able to run your application as a CGI script so ExecCGI must be
302enabled for the directory.
303
304 AddHandler fastcgi-script .fcgi
305
306The above tells Apache to run any .fcgi file as a FastCGI application.
307
308Here is a complete example:
309
310 <VirtualHost *:80>
311 ServerName www.myapp.com
312 DocumentRoot /path/to/MyApp
313
314 # Allow CGI script to run
315 <Directory /path/to/MyApp>
316 Options +ExecCGI
317 </Directory>
318
319 # Tell Apache this is a FastCGI application
320 <Files myapp_fastcgi.pl>
321 SetHandler fastcgi-script
322 </Files>
198b0efa 323 </VirtualHost>
d7d72ad9 324
325Then a request for /script/myapp_fastcgi.pl will run the
326application.
ac5c933b 327
198b0efa 328For more information on using FastCGI under Apache, visit
329L<http://www.fastcgi.com/mod_fastcgi/docs/mod_fastcgi.html>
330
25f55123 331=head3 Authorization header with mod_fastcgi or mod_cgi
332
333By default, mod_fastcgi/mod_cgi do not pass along the Authorization header,
334so modules like C<Catalyst::Plugin::Authentication::Credential::HTTP> will
335not work. To enable pass-through of this header, add the following
336mod_rewrite directives:
337
338 RewriteCond %{HTTP:Authorization} ^(.+)
339 RewriteRule ^(.*)$ $1 [E=HTTP_AUTHORIZATION:%1,PT]
340
198b0efa 341=head2 Lighttpd
342
d7d72ad9 343These configurations were tested with Lighttpd 1.4.7.
344
345=head3 Standalone server mode
346
347 server.document-root = "/var/www/MyApp/root"
348
349 fastcgi.server = (
350 "" => (
351 "MyApp" => (
352 "socket" => "/tmp/myapp.socket",
353 "check-local" => "disable"
354 )
355 )
356 )
357
358=head3 Static mode
198b0efa 359
360 server.document-root = "/var/www/MyApp/root"
ac5c933b 361
198b0efa 362 fastcgi.server = (
363 "" => (
364 "MyApp" => (
365 "socket" => "/tmp/myapp.socket",
366 "check-local" => "disable",
367 "bin-path" => "/var/www/MyApp/script/myapp_fastcgi.pl",
368 "min-procs" => 2,
369 "max-procs" => 5,
370 "idle-timeout" => 20
371 )
372 )
373 )
ac5c933b 374
d7d72ad9 375Note that in newer versions of lighttpd, the min-procs and idle-timeout
376values are disabled. The above example would start 5 processes.
25810c41 377
d7d72ad9 378=head3 Non-root configuration
ac5c933b 379
d7d72ad9 380You can also run your application at any non-root location with either of the
381above modes.
198b0efa 382
383 fastcgi.server = (
d7d72ad9 384 "/myapp" => (
198b0efa 385 "MyApp" => (
d7d72ad9 386 # same as above
198b0efa 387 )
388 )
389 )
390
391For more information on using FastCGI under Lighttpd, visit
392L<http://www.lighttpd.net/documentation/fastcgi.html>
393
394=head2 IIS
395
396It is possible to run Catalyst under IIS with FastCGI, but we do not
397yet have detailed instructions.
398
fbcc39ad 399=head1 SEE ALSO
e2fd5b5f 400
fbcc39ad 401L<Catalyst>, L<FCGI>.
cd3bb248 402
fbcc39ad 403=head1 AUTHORS
ffb41d94 404
fbcc39ad 405Sebastian Riedel, <sri@cpan.org>
ffb41d94 406
fbcc39ad 407Christian Hansen, <ch@ngmedia.com>
ffb41d94 408
fbcc39ad 409Andy Grundman, <andy@hybridized.org>
ffb41d94 410
d7d72ad9 411=head1 THANKS
412
413Bill Moseley, for documentation updates and testing.
414
ffb41d94 415=head1 COPYRIGHT
416
417This program is free software, you can redistribute it and/or modify it under
418the same terms as Perl itself.
419
420=cut