Fixed run-on sentence in COPYRIGHT and s/program/library/
[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)
cfd31158 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();
cfd31158 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();
cfd31158 144
c46dd4e8 145 $self->_fix_env( \%env );
cfd31158 146
84528885 147 $class->handle_request( env => \%env );
cfd31158 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
02570318 160 unless ( $self->_prepared_write ) {
4f5ebacd 161 $self->prepare_write($c);
02570318 162 $self->_prepared_write(1);
fbcc39ad 163 }
ac5c933b 164
e512dd24 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
ac5c933b 168
e512dd24 169 # Prepend the headers if they have not yet been sent
02570318 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
c46dd4e8 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
0c913601 223 # we are gonna add variables from current system environment %ENV to %env
224 # that contains at this moment just variables taken from FastCGI request
225 foreach my $k (keys(%ENV)) {
226 $env->{$k} = $ENV{$k} unless defined($env->{$k});
227 }
228
c46dd4e8 229 return unless ( $env->{SERVER_SOFTWARE} );
230
231 # If we're running under Lighttpd, swap PATH_INFO and SCRIPT_NAME
232 # http://lists.scsys.co.uk/pipermail/catalyst/2006-June/008361.html
233 # Thanks to Mark Blythe for this fix
234 if ( $env->{SERVER_SOFTWARE} =~ /lighttpd/ ) {
235 $env->{PATH_INFO} ||= delete $env->{SCRIPT_NAME};
236 }
98a13b51 237 # Fix the environment variables PATH_INFO and SCRIPT_NAME when running under IIS
238 elsif ( $env->{SERVER_SOFTWARE} =~ /IIS\/[67].0/ ) {
c46dd4e8 239 my @script_name = split(m!/!, $env->{PATH_INFO});
240 my @path_translated = split(m!/|\\\\?!, $env->{PATH_TRANSLATED});
241 my @path_info;
242
243 while ($script_name[$#script_name] eq $path_translated[$#path_translated]) {
244 pop(@path_translated);
245 unshift(@path_info, pop(@script_name));
246 }
247
248 unshift(@path_info, '', '');
249
250 $env->{PATH_INFO} = join('/', @path_info);
251 $env->{SCRIPT_NAME} = join('/', @script_name);
252 }
253}
254
198b0efa 2551;
256__END__
257
198b0efa 258=head1 WEB SERVER CONFIGURATIONS
259
d7d72ad9 260=head2 Standalone FastCGI Server
261
ac5c933b 262In server mode the application runs as a standalone server and accepts
d7d72ad9 263connections from a web server. The application can be on the same machine as
264the web server, on a remote machine, or even on multiple remote machines.
265Advantages of this method include running the Catalyst application as a
266different user than the web server, and the ability to set up a scalable
267server farm.
198b0efa 268
d7d72ad9 269To start your application in server mode, install the FCGI::ProcManager
270module and then use the included fastcgi.pl script.
198b0efa 271
d7d72ad9 272 $ script/myapp_fastcgi.pl -l /tmp/myapp.socket -n 5
ac5c933b 273
d7d72ad9 274Command line options for fastcgi.pl include:
275
276 -d -daemon Daemonize the server.
277 -p -pidfile Write a pidfile with the pid of the process manager.
278 -l -listen Listen on a socket path, hostname:port, or :port.
279 -n -nproc The number of processes started to handle requests.
ac5c933b 280
d7d72ad9 281See below for the specific web server configurations for using the external
282server.
198b0efa 283
d7d72ad9 284=head2 Apache 1.x, 2.x
285
286Apache requires the mod_fastcgi module. The same module supports both
287Apache 1 and 2.
288
ac5c933b 289There are three ways to run your application under FastCGI on Apache: server,
d7d72ad9 290static, and dynamic.
291
292=head3 Standalone server mode
293
3f0911d3 294 FastCgiExternalServer /tmp/myapp.fcgi -socket /tmp/myapp.socket
295 Alias /myapp/ /tmp/myapp/myapp.fcgi/
ac5c933b 296
d7d72ad9 297 # Or, run at the root
3f0911d3 298 Alias / /tmp/myapp.fcgi/
ac5c933b 299
d7d72ad9 300 # Optionally, rewrite the path when accessed without a trailing slash
301 RewriteRule ^/myapp$ myapp/ [R]
ac5c933b 302
3f0911d3 303
304The FastCgiExternalServer directive tells Apache that when serving
305/tmp/myapp to use the FastCGI application listenting on the socket
303c087d 306/tmp/mapp.socket. Note that /tmp/myapp.fcgi B<MUST NOT> exist --
3f0911d3 307it's a virtual file name. With some versions of C<mod_fastcgi> or
303c087d 308C<mod_fcgid>, you can use any name you like, but some require that the
3f0911d3 309virtual filename end in C<.fcgi>.
d7d72ad9 310
ac5c933b 311It's likely that Apache is not configured to serve files in /tmp, so the
d7d72ad9 312Alias directive maps the url path /myapp/ to the (virtual) file that runs the
313FastCGI application. The trailing slashes are important as their use will
314correctly set the PATH_INFO environment variable used by Catalyst to
315determine the request path. If you would like to be able to access your app
316without a trailing slash (http://server/myapp), you can use the above
317RewriteRule directive.
318
319=head3 Static mode
320
321The term 'static' is misleading, but in static mode Apache uses its own
322FastCGI Process Manager to start the application processes. This happens at
323Apache startup time. In this case you do not run your application's
324fastcgi.pl script -- that is done by Apache. Apache then maps URIs to the
325FastCGI script to run your application.
326
327 FastCgiServer /path/to/myapp/script/myapp_fastcgi.pl -processes 3
328 Alias /myapp/ /path/to/myapp/script/myapp_fastcgi.pl/
ac5c933b 329
d7d72ad9 330FastCgiServer tells Apache to start three processes of your application at
331startup. The Alias command maps a path to the FastCGI application. Again,
332the trailing slashes are important.
ac5c933b 333
d7d72ad9 334=head3 Dynamic mode
335
ac5c933b 336In FastCGI dynamic mode, Apache will run your application on demand,
d7d72ad9 337typically by requesting a file with a specific extension (e.g. .fcgi). ISPs
338often use this type of setup to provide FastCGI support to many customers.
339
340In this mode it is often enough to place or link your *_fastcgi.pl script in
341your cgi-bin directory with the extension of .fcgi. In dynamic mode Apache
342must be able to run your application as a CGI script so ExecCGI must be
343enabled for the directory.
344
345 AddHandler fastcgi-script .fcgi
346
347The above tells Apache to run any .fcgi file as a FastCGI application.
348
349Here is a complete example:
350
351 <VirtualHost *:80>
352 ServerName www.myapp.com
353 DocumentRoot /path/to/MyApp
354
355 # Allow CGI script to run
356 <Directory /path/to/MyApp>
357 Options +ExecCGI
358 </Directory>
359
360 # Tell Apache this is a FastCGI application
361 <Files myapp_fastcgi.pl>
362 SetHandler fastcgi-script
363 </Files>
198b0efa 364 </VirtualHost>
d7d72ad9 365
366Then a request for /script/myapp_fastcgi.pl will run the
367application.
ac5c933b 368
198b0efa 369For more information on using FastCGI under Apache, visit
370L<http://www.fastcgi.com/mod_fastcgi/docs/mod_fastcgi.html>
371
25f55123 372=head3 Authorization header with mod_fastcgi or mod_cgi
373
374By default, mod_fastcgi/mod_cgi do not pass along the Authorization header,
375so modules like C<Catalyst::Plugin::Authentication::Credential::HTTP> will
376not work. To enable pass-through of this header, add the following
377mod_rewrite directives:
378
379 RewriteCond %{HTTP:Authorization} ^(.+)
380 RewriteRule ^(.*)$ $1 [E=HTTP_AUTHORIZATION:%1,PT]
381
198b0efa 382=head2 Lighttpd
383
d7d72ad9 384These configurations were tested with Lighttpd 1.4.7.
385
386=head3 Standalone server mode
387
388 server.document-root = "/var/www/MyApp/root"
389
390 fastcgi.server = (
391 "" => (
392 "MyApp" => (
393 "socket" => "/tmp/myapp.socket",
394 "check-local" => "disable"
395 )
396 )
397 )
398
399=head3 Static mode
198b0efa 400
401 server.document-root = "/var/www/MyApp/root"
ac5c933b 402
198b0efa 403 fastcgi.server = (
404 "" => (
405 "MyApp" => (
406 "socket" => "/tmp/myapp.socket",
407 "check-local" => "disable",
408 "bin-path" => "/var/www/MyApp/script/myapp_fastcgi.pl",
409 "min-procs" => 2,
410 "max-procs" => 5,
411 "idle-timeout" => 20
412 )
413 )
414 )
ac5c933b 415
d7d72ad9 416Note that in newer versions of lighttpd, the min-procs and idle-timeout
417values are disabled. The above example would start 5 processes.
25810c41 418
d7d72ad9 419=head3 Non-root configuration
ac5c933b 420
d7d72ad9 421You can also run your application at any non-root location with either of the
2f381252 422above modes. Note the required mod_rewrite rule.
198b0efa 423
2f381252 424 url.rewrite = ( "myapp\$" => "myapp/" )
198b0efa 425 fastcgi.server = (
d7d72ad9 426 "/myapp" => (
198b0efa 427 "MyApp" => (
d7d72ad9 428 # same as above
198b0efa 429 )
430 )
431 )
432
433For more information on using FastCGI under Lighttpd, visit
434L<http://www.lighttpd.net/documentation/fastcgi.html>
435
da7aac2e 436=head2 Microsoft IIS
198b0efa 437
da7aac2e 438It is possible to run Catalyst under IIS with FastCGI, but only on IIS 6.0
439(Microsoft Windows 2003), IIS 7.0 (Microsoft Windows 2008 and Vista) and
440hopefully its successors.
441
442Even if it is declared that FastCGI is supported on IIS 5.1 (Windows XP) it
443does not support some features (specifically: wildcard mappings) that prevents
444running Catalyst application.
445
446Let us assume that our server has the following layout:
447
448 d:\WWW\WebApp\ path to our Catalyst application
449 d:\strawberry\perl\bin\perl.exe path to perl interpreter (with Catalyst installed)
450 c:\windows Windows directory
451
452=head3 Setup IIS 6.0 (Windows 2003)
453
4a6f54df 454=over 4
455
456=item Install FastCGI extension for IIS 6.0
da7aac2e 457
458FastCGI is not a standard part of IIS 6 - you have to install it separately. For
459more info and download go to L<http://www.iis.net/extensions/FastCGI>. Choose
460approptiate version (32-bit/64-bit), installation is quite simple
461(in fact no questions, no options).
462
4a6f54df 463=item Create a new website
da7aac2e 464
465Open "Control Panel" > "Administrative Tools" > "Internet Information Services Manager".
466Click "Action" > "New" > "Web Site". After you finish the installation wizard
467you need to go to the new website's properties.
468
4a6f54df 469=item Set website properties
da7aac2e 470
471On tab "Web site" set proper values for:
472Site Description, IP Address, TCP Port, SSL Port etc.
473
474On tab "Home Directory" set the following:
475
476 Local path: "d:\WWW\WebApp\root"
477 Local path permission flags: check only "Read" + "Log visits"
478 Execute permitions: "Scripts only"
479
480Click "Configuration" button (still on Home Directory tab) then click "Insert"
481the wildcard application mapping and in the next dialog set:
482
483 Executable: "c:\windows\system32\inetsrv\fcgiext.dll"
484 Uncheck: "Verify that file exists"
485
486Close all dialogs with "OK".
487
4a6f54df 488=item Edit fcgiext.ini
da7aac2e 489
490Put the following lines into c:\windows\system32\inetsrv\fcgiext.ini (on 64-bit
491system c:\windows\syswow64\inetsrv\fcgiext.ini):
492
493 [Types]
494 *:8=CatalystApp
495 ;replace 8 with the identification number of the newly created website
496 ;it is not so easy to get this number:
497 ; - you can use utility "c:\inetpub\adminscripts\adsutil.vbs"
498 ; to list websites: "cscript adsutil.vbs ENUM /P /W3SVC"
499 ; to get site name: "cscript adsutil.vbs GET /W3SVC/<number>/ServerComment"
500 ; to get all details: "cscript adsutil.vbs GET /W3SVC/<number>"
501 ; - or look where are the logs located:
502 ; c:\WINDOWS\SYSTEM32\Logfiles\W3SVC7\whatever.log
503 ; means that the corresponding number is "7"
504 ;if you are running just one website using FastCGI you can use '*=CatalystApp'
505
506 [CatalystApp]
507 ExePath=d:\strawberry\perl\bin\perl.exe
508 Arguments="d:\WWW\WebApp\script\webapp_fastcgi.pl -e"
509
510 ;by setting this you can instruct IIS to serve Catalyst static files
511 ;directly not via FastCGI (in case of any problems try 1)
512 IgnoreExistingFiles=0
513
514 ;do not be fooled by Microsoft doc talking about "IgnoreExistingDirectories"
515 ;that does not work and use "IgnoreDirectories" instead
516 IgnoreDirectories=1
517
4a6f54df 518=back
519
da7aac2e 520=head3 Setup IIS 7.0 (Windows 2008 and Vista)
521
522Microsoft IIS 7.0 has built-in support for FastCGI so you do not have to install
523any addons.
524
4a6f54df 525=over 4
526
527=item Necessary steps during IIS7 installation
da7aac2e 528
529During IIS7 installation after you have added role "Web Server (IIS)"
530you need to check to install role feature "CGI" (do not be nervous that it is
531not FastCGI). If you already have IIS7 installed you can add "CGI" role feature
532through "Control panel" > "Programs and Features".
533
4a6f54df 534=item Create a new website
da7aac2e 535
536Open "Control Panel" > "Administrative Tools" > "Internet Information Services Manager"
537> "Add Web Site".
538
539 site name: "CatalystSite"
540 content directory: "d:\WWW\WebApp\root"
541 binding: set proper IP address, port etc.
542
4a6f54df 543=item Configure FastCGI
da7aac2e 544
545You can configure FastCGI extension using commandline utility
546"c:\windows\system32\inetsrv\appcmd.exe"
547
4a6f54df 548=over 4
549
550=item Configuring section "fastCgi" (it is a global setting)
da7aac2e 551
4a6f54df 552 appcmd.exe set config -section:system.webServer/fastCgi /+"[fullPath='d:\strawberry\perl\bin\perl.exe',arguments='d:\www\WebApp\script\webapp_fastcgi.pl -e',maxInstances='4',idleTimeout='300',activityTimeout='30',requestTimeout='90',instanceMaxRequests='1000',protocol='NamedPipe',flushNamedPipe='False']" /commit:apphost
da7aac2e 553
4a6f54df 554=item Configuring proper handler (it is a site related setting)
da7aac2e 555
4a6f54df 556 appcmd.exe set config "CatalystSite" -section:system.webServer/handlers /+"[name='CatalystFastCGI',path='*',verb='GET,HEAD,POST',modules='FastCgiModule',scriptProcessor='d:\strawberry\perl\bin\perl.exe|d:\www\WebApp\script\webapp_fastcgi.pl -e',resourceType='Unspecified',requireAccess='Script']" /commit:apphost
da7aac2e 557
558Note: before launching the commands above do not forget to change site
559name and paths to values relevant for your server setup.
198b0efa 560
4a6f54df 561=back
562
563=back
564
fbcc39ad 565=head1 SEE ALSO
e2fd5b5f 566
fbcc39ad 567L<Catalyst>, L<FCGI>.
cd3bb248 568
fbcc39ad 569=head1 AUTHORS
ffb41d94 570
2f381252 571Catalyst Contributors, see Catalyst.pm
ffb41d94 572
d7d72ad9 573=head1 THANKS
574
575Bill Moseley, for documentation updates and testing.
576
ffb41d94 577=head1 COPYRIGHT
578
536bee89 579This library is free software. You can redistribute it and/or modify it under
ffb41d94 580the same terms as Perl itself.
581
582=cut