r12983@zaphod: kd | 2008-04-28 18:10:27 +1000
[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 =item nointr
50
51 Do not allow the listener to be interrupted by Ctrl+C
52
53 =item nproc
54
55 Specify a number of processes for FCGI::ProcManager
56
57 =item pidfile
58
59 Specify a filename for the pid file
60
61 =item manager
62
63 Specify a FCGI::ProcManager sub-class
64
65 =item detach          
66
67 Detach from console
68
69 =item keep_stderr
70
71 Send STDERR to STDOUT instead of the webserver
72
73 =back
74
75 =cut
76
77 sub run {
78     my ( $self, $class, $listen, $options ) = @_;
79
80     my $sock = 0;
81     if ($listen) {
82         my $old_umask = umask;
83         unless ( $options->{leave_umask} ) {
84             umask(0);
85         }
86         $sock = FCGI::OpenSocket( $listen, 100 )
87           or die "failed to open FastCGI socket; $!";
88         unless ( $options->{leave_umask} ) {
89             umask($old_umask);
90         }
91     }
92     elsif ( $^O ne 'MSWin32' ) {
93         -S STDIN
94           or die "STDIN is not a socket; specify a listen location";
95     }
96
97     $options ||= {};
98
99     my %env;
100     my $error = \*STDERR; # send STDERR to the web server
101        $error = \*STDOUT  # send STDERR to stdout (a logfile)
102          if $options->{keep_stderr}; # (if asked to)
103     
104     my $request =
105       FCGI::Request( \*STDIN, \*STDOUT, $error, \%env, $sock,
106         ( $options->{nointr} ? 0 : &FCGI::FAIL_ACCEPT_ON_INTR ),
107       );
108
109     my $proc_manager;
110
111     if ($listen) {
112         $options->{manager} ||= "FCGI::ProcManager";
113         $options->{nproc}   ||= 1;
114
115         $self->daemon_fork() if $options->{detach};
116
117         if ( $options->{manager} ) {
118             eval "use $options->{manager}; 1" or die $@;
119
120             $proc_manager = $options->{manager}->new(
121                 {
122                     n_processes => $options->{nproc},
123                     pid_fname   => $options->{pidfile},
124                 }
125             );
126
127             # detach *before* the ProcManager inits
128             $self->daemon_detach() if $options->{detach};
129
130             $proc_manager->pm_manage();
131         }
132         elsif ( $options->{detach} ) {
133             $self->daemon_detach();
134         }
135     }
136
137     while ( $request->Accept >= 0 ) {
138         $proc_manager && $proc_manager->pm_pre_dispatch();
139         
140         # If we're running under Lighttpd, swap PATH_INFO and SCRIPT_NAME
141         # http://lists.rawmode.org/pipermail/catalyst/2006-June/008361.html
142         # Thanks to Mark Blythe for this fix
143         if ( $env{SERVER_SOFTWARE} && $env{SERVER_SOFTWARE} =~ /lighttpd/ ) {
144             $env{PATH_INFO} ||= delete $env{SCRIPT_NAME};
145         }
146         
147         $class->handle_request( env => \%env );
148         
149         $proc_manager && $proc_manager->pm_post_dispatch();
150     }
151 }
152
153 =head2 $self->write($c, $buffer)
154
155 =cut
156
157 sub write {
158     my ( $self, $c, $buffer ) = @_;
159
160     unless ( $self->{_prepared_write} ) {
161         $self->prepare_write($c);
162         $self->{_prepared_write} = 1;
163     }
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
170     if ( my $headers = delete $self->{_header_buf} ) {
171         $buffer = $headers . $buffer;
172     }
173
174     # FastCGI does not stream data properly if using 'print $handle',
175     # but a syswrite appears to work properly.
176     *STDOUT->syswrite($buffer);
177 }
178
179 =head2 $self->daemon_fork()
180
181 Performs the first part of daemon initialisation.  Specifically,
182 forking.  STDERR, etc are still connected to a terminal.
183
184 =cut
185
186 sub daemon_fork {
187     require POSIX;
188     fork && exit;
189 }
190
191 =head2 $self->daemon_detach( )
192
193 Performs the second part of daemon initialisation.  Specifically,
194 disassociates from the terminal.
195
196 However, this does B<not> change the current working directory to "/",
197 as normal daemons do.  It also does not close all open file
198 descriptors (except STDIN, STDOUT and STDERR, which are re-opened from
199 F</dev/null>).
200
201 =cut
202
203 sub daemon_detach {
204     my $self = shift;
205     print "FastCGI daemon started (pid $$)\n";
206     open STDIN,  "+</dev/null" or die $!;
207     open STDOUT, ">&STDIN"     or die $!;
208     open STDERR, ">&STDIN"     or die $!;
209     POSIX::setsid();
210 }
211
212 1;
213 __END__
214
215 =head1 WEB SERVER CONFIGURATIONS
216
217 =head2 Standalone FastCGI Server
218
219 In server mode the application runs as a standalone server and accepts 
220 connections from a web server.  The application can be on the same machine as
221 the web server, on a remote machine, or even on multiple remote machines.
222 Advantages of this method include running the Catalyst application as a
223 different user than the web server, and the ability to set up a scalable
224 server farm.
225
226 To start your application in server mode, install the FCGI::ProcManager
227 module and then use the included fastcgi.pl script.
228
229     $ script/myapp_fastcgi.pl -l /tmp/myapp.socket -n 5
230     
231 Command line options for fastcgi.pl include:
232
233     -d -daemon     Daemonize the server.
234     -p -pidfile    Write a pidfile with the pid of the process manager.
235     -l -listen     Listen on a socket path, hostname:port, or :port.
236     -n -nproc      The number of processes started to handle requests.
237     
238 See below for the specific web server configurations for using the external
239 server.
240
241 =head2 Apache 1.x, 2.x
242
243 Apache requires the mod_fastcgi module.  The same module supports both
244 Apache 1 and 2.
245
246 There are three ways to run your application under FastCGI on Apache: server, 
247 static, and dynamic.
248
249 =head3 Standalone server mode
250
251     FastCgiExternalServer /tmp/myapp.fcgi -socket /tmp/myapp.socket
252     Alias /myapp/ /tmp/myapp/myapp.fcgi/
253     
254     # Or, run at the root
255     Alias / /tmp/myapp.fcgi/
256     
257     # Optionally, rewrite the path when accessed without a trailing slash
258     RewriteRule ^/myapp$ myapp/ [R]
259     
260
261 The FastCgiExternalServer directive tells Apache that when serving
262 /tmp/myapp to use the FastCGI application listenting on the socket
263 /tmp/mapp.socket.  Note that /tmp/myapp.fcgi does not need to exist --
264 it's a virtual file name.  With some versions of C<mod_fastcgi> or
265 C<mod_fcgid>, you can use any name you like, but most require that the
266 virtual filename end in C<.fcgi>.
267
268 It's likely that Apache is not configured to serve files in /tmp, so the 
269 Alias directive maps the url path /myapp/ to the (virtual) file that runs the
270 FastCGI application. The trailing slashes are important as their use will
271 correctly set the PATH_INFO environment variable used by Catalyst to
272 determine the request path.  If you would like to be able to access your app
273 without a trailing slash (http://server/myapp), you can use the above
274 RewriteRule directive.
275
276 =head3 Static mode
277
278 The term 'static' is misleading, but in static mode Apache uses its own
279 FastCGI Process Manager to start the application processes.  This happens at
280 Apache startup time.  In this case you do not run your application's
281 fastcgi.pl script -- that is done by Apache. Apache then maps URIs to the
282 FastCGI script to run your application.
283
284     FastCgiServer /path/to/myapp/script/myapp_fastcgi.pl -processes 3
285     Alias /myapp/ /path/to/myapp/script/myapp_fastcgi.pl/
286     
287 FastCgiServer tells Apache to start three processes of your application at
288 startup.  The Alias command maps a path to the FastCGI application. Again,
289 the trailing slashes are important.
290     
291 =head3 Dynamic mode
292
293 In FastCGI dynamic mode, Apache will run your application on demand, 
294 typically by requesting a file with a specific extension (e.g. .fcgi).  ISPs
295 often use this type of setup to provide FastCGI support to many customers.
296
297 In this mode it is often enough to place or link your *_fastcgi.pl script in
298 your cgi-bin directory with the extension of .fcgi.  In dynamic mode Apache
299 must be able to run your application as a CGI script so ExecCGI must be
300 enabled for the directory.
301
302     AddHandler fastcgi-script .fcgi
303
304 The above tells Apache to run any .fcgi file as a FastCGI application.
305
306 Here is a complete example:
307
308     <VirtualHost *:80>
309         ServerName www.myapp.com
310         DocumentRoot /path/to/MyApp
311
312         # Allow CGI script to run
313         <Directory /path/to/MyApp>
314             Options +ExecCGI
315         </Directory>
316
317         # Tell Apache this is a FastCGI application
318         <Files myapp_fastcgi.pl>
319             SetHandler fastcgi-script
320         </Files>
321     </VirtualHost>
322
323 Then a request for /script/myapp_fastcgi.pl will run the
324 application.
325     
326 For more information on using FastCGI under Apache, visit
327 L<http://www.fastcgi.com/mod_fastcgi/docs/mod_fastcgi.html>
328
329 =head3 Authorization header with mod_fastcgi or mod_cgi
330
331 By default, mod_fastcgi/mod_cgi do not pass along the Authorization header,
332 so modules like C<Catalyst::Plugin::Authentication::Credential::HTTP> will
333 not work.  To enable pass-through of this header, add the following
334 mod_rewrite directives:
335
336     RewriteCond %{HTTP:Authorization} ^(.+)
337     RewriteRule ^(.*)$ $1 [E=HTTP_AUTHORIZATION:%1,PT]
338
339 =head2 Lighttpd
340
341 These configurations were tested with Lighttpd 1.4.7.
342
343 =head3 Standalone server mode
344
345     server.document-root = "/var/www/MyApp/root"
346
347     fastcgi.server = (
348         "" => (
349             "MyApp" => (
350                 "socket"      => "/tmp/myapp.socket",
351                 "check-local" => "disable"
352             )
353         )
354     )
355
356 =head3 Static mode
357
358     server.document-root = "/var/www/MyApp/root"
359     
360     fastcgi.server = (
361         "" => (
362             "MyApp" => (
363                 "socket"       => "/tmp/myapp.socket",
364                 "check-local"  => "disable",
365                 "bin-path"     => "/var/www/MyApp/script/myapp_fastcgi.pl",
366                 "min-procs"    => 2,
367                 "max-procs"    => 5,
368                 "idle-timeout" => 20
369             )
370         )
371     )
372     
373 Note that in newer versions of lighttpd, the min-procs and idle-timeout
374 values are disabled.  The above example would start 5 processes.
375
376 =head3 Non-root configuration
377     
378 You can also run your application at any non-root location with either of the
379 above modes.  Note the required mod_rewrite rule.
380
381     url.rewrite = ( "myapp\$" => "myapp/" )
382     fastcgi.server = (
383         "/myapp" => (
384             "MyApp" => (
385                 # same as above
386             )
387         )
388     )
389
390 For more information on using FastCGI under Lighttpd, visit
391 L<http://www.lighttpd.net/documentation/fastcgi.html>
392
393 =head2 IIS
394
395 It is possible to run Catalyst under IIS with FastCGI, but we do not
396 yet have detailed instructions.
397
398 =head1 SEE ALSO
399
400 L<Catalyst>, L<FCGI>.
401
402 =head1 AUTHORS
403
404 Catalyst Contributors, see Catalyst.pm
405
406 =head1 THANKS
407
408 Bill Moseley, for documentation updates and testing.
409
410 =head1 COPYRIGHT
411
412 This program is free software, you can redistribute it and/or modify it under
413 the same terms as Perl itself.
414
415 =cut