Fixed FastCGI engine to not clobber the global %ENV on each request (Sam Vilain)
[catagits/Catalyst-Runtime.git] / lib / Catalyst / Engine / FastCGI.pm
1 package Catalyst::Engine::FastCGI;
2
3 use strict;
4 use base 'Catalyst::Engine::CGI';
5 use FCGI;
6
7 =head1 NAME
8
9 Catalyst::Engine::FastCGI - FastCGI Engine
10
11 =head1 DESCRIPTION
12
13 This is the FastCGI engine.
14
15 =head1 OVERLOADED METHODS
16
17 This class overloads some methods from C<Catalyst::Engine::CGI>.
18
19 =over 4
20
21 =item $self->run($c, $listen, { option => value, ... })
22  
23 Starts the FastCGI server.  If C<$listen> is set, then it specifies a
24 location to listen for FastCGI requests;
25
26   Form            Meaning
27   /path           listen via Unix sockets on /path
28   :port           listen via TCP on port on all interfaces
29   hostname:port   listen via TCP on port bound to hostname
30
31 Options may also be specified;
32
33   Option          Meaning
34   leave_umask     Set to 1 to disable setting umask to 0
35                   for socket open
36   nointr          Do not allow the listener to be
37                   interrupted by Ctrl+C
38   nproc           Specify a number of processes for
39                   FCGI::ProcManager
40
41 =cut
42
43 sub run {
44     my ( $self, $class, $listen, $options ) = @_;
45
46     my $sock;
47     if ($listen) {
48         my $old_umask = umask;
49         unless ( $options->{leave_umask} ) {
50             umask(0);
51         }
52         $sock = FCGI::OpenSocket( $listen, 100 )
53           or die "failed to open FastCGI socket; $!";
54         unless ( $options->{leave_umask} ) {
55             umask($old_umask);
56         }
57     }
58     else {
59         -S STDIN
60           or die "STDIN is not a socket; specify a listen location";
61     }
62
63     $options ||= {};
64     
65     my %env;
66
67     my $request =
68       FCGI::Request( \*STDIN, \*STDOUT, \*STDERR, \%env, $sock,
69         ( $options->{nointr} ? 0 : &FCGI::FAIL_ACCEPT_ON_INTR ),
70       );
71
72     my $proc_manager;
73
74     if ( $listen and ( $options->{nproc} || 1 ) > 1 ) {
75         require FCGI::ProcManager;
76         $proc_manager =
77           FCGI::ProcManager->new( { n_processes => $options->{nproc} } );
78         $proc_manager->pm_manage();
79     }
80
81     while ( $request->Accept >= 0 ) {
82         $proc_manager && $proc_manager->pm_pre_dispatch();
83         $class->handle_request( env => \%env );
84         $proc_manager && $proc_manager->pm_pre_dispatch();
85     }
86 }
87
88 =item $self->write($c, $buffer)
89
90 =cut
91
92 sub write {
93     my ( $self, $c, $buffer ) = @_;
94
95     unless ( $self->{_prepared_write} ) {
96         $self->prepare_write($c);
97         $self->{_prepared_write} = 1;
98     }
99
100     # FastCGI does not stream data properly if using 'print $handle',
101     # but a syswrite appears to work properly.
102     *STDOUT->syswrite($buffer);
103 }
104
105 1;
106 __END__
107
108 =back
109
110 =head1 WEB SERVER CONFIGURATIONS
111
112 =head2 Apache 1.x, 2.x
113
114 Apache requires the mod_fastcgi module.  The following config will let Apache
115 control the running of your FastCGI processes.
116
117     # Launch the FastCGI processes
118     FastCgiIpcDir /tmp
119     FastCgiServer /var/www/MyApp/script/myapp_fastcgi.pl -idle_timeout 300 -processes 5
120     
121     <VirtualHost *>
122         ScriptAlias / /var/www/MyApp/script/myapp_fastcgi.pl/
123     </VirtualHost>
124     
125 You can also tell Apache to connect to an external FastCGI server:
126
127     # Start the external server (requires FCGI::ProcManager)
128     $ script/myapp_fastcgi.pl -l /tmp/myapp.socket -n 5
129     
130     # Note that the path used in FastCgiExternalServer can be any path
131     FastCgiIpcDir /tmp
132     FastCgiExternalServer /tmp/myapp_fastcgi.pl -socket /tmp/myapp.socket
133     
134     <VirtualHost *>
135         ScriptAlias / /tmp/myapp_fastcgi.pl/
136     </VirtualHost>
137     
138 For more information on using FastCGI under Apache, visit
139 L<http://www.fastcgi.com/mod_fastcgi/docs/mod_fastcgi.html>
140
141 =head2 Lighttpd
142
143 This configuration was tested with Lighttpd 1.4.7.
144
145     server.document-root = "/var/www/MyApp/root"
146     
147     fastcgi.server = (
148         "" => (
149             "MyApp" => (
150                 "socket"       => "/tmp/myapp.socket",
151                 "check-local"  => "disable",
152                 "bin-path"     => "/var/www/MyApp/script/myapp_fastcgi.pl",
153                 "min-procs"    => 2,
154                 "max-procs"    => 5,
155                 "idle-timeout" => 20
156             )
157         )
158     )
159     
160 You can also run your application at any non-root location.
161
162     fastcgi.server = (
163         "/myapp" => (
164             "MyApp" => (
165                 # same as above
166             )
167         )
168     )
169     
170 You can also use an external server:
171
172     # Start the external server (requires FCGI::ProcManager)
173     $ script/myapp_fastcgi.pl -l /tmp/myapp.socket -n 5
174
175     server.document-root = "/var/www/MyApp/root"
176
177     fastcgi.server = (
178         "" => (
179             "MyApp" => (
180                 "socket"      => "/tmp/myapp.socket",
181                 "check-local" => "disable"
182             )
183         )
184     )
185
186 For more information on using FastCGI under Lighttpd, visit
187 L<http://www.lighttpd.net/documentation/fastcgi.html>
188
189 =head2 IIS
190
191 It is possible to run Catalyst under IIS with FastCGI, but we do not
192 yet have detailed instructions.
193
194 =head1 SEE ALSO
195
196 L<Catalyst>, L<FCGI>.
197
198 =head1 AUTHORS
199
200 Sebastian Riedel, <sri@cpan.org>
201
202 Christian Hansen, <ch@ngmedia.com>
203
204 Andy Grundman, <andy@hybridized.org>
205
206 =head1 COPYRIGHT
207
208 This program is free software, you can redistribute it and/or modify it under
209 the same terms as Perl itself.
210
211 =cut