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