root/lang/perl/HTTP-Engine/branches/interface-declare/lib/HTTP/Engine/Interface/FCGI.pm @ 18227

Revision 18227, 4.1 kB (checked in by tokuhirom, 5 years ago)

set builder/writer at import

Line 
1package HTTP::Engine::Interface::FCGI;
2use HTTP::Engine::Interface
3    builder => 'CGI',
4    writer  => {
5        response_line => 1,
6        'write' => sub {
7            my ($self, $buffer) = @_;
8            *STDOUT->syswrite($buffer);
9        },
10    }
11;
12# XXX: We can't use Engine's write() method because syswrite
13# appears to return bogus values instead of the number of bytes
14# written: http://www.fastcgi.com/om_archive/mail-archive/0128.html
15
16# FastCGI does not stream data properly if using 'print $handle',
17# but a syswrite appears to work properly.
18
19use constant RUNNING_IN_HELL => $^O eq 'MSWin32';
20use FCGI;
21
22has leave_umask => (
23    is      => 'ro',
24    isa     => 'Bool',
25    default => 0,
26);
27
28has keep_stderr => (
29    is      => 'ro',
30    isa     => 'Bool',
31    default => 0,
32);
33
34has nointr => (
35    is      => 'ro',
36    isa     => 'Bool',
37    default => 0,
38);
39
40has detach => (
41    is      => 'ro',
42    isa     => 'Bool',
43    default => 0,
44);
45
46has manager => (
47    is      => 'ro',
48    isa     => 'Str',
49    default => "FCGI::ProcManager",
50);
51
52has nproc => (
53    is      => 'ro',
54    isa     => 'Int',
55    default => 1,
56);
57
58has pidfile => (
59    is      => 'ro',
60    isa     => 'Str',
61);
62
63has listen => (
64    is  => 'ro',
65    isa => 'Str',
66);
67
68sub run {
69    my ( $self, ) = @_;
70
71    my $sock = 0;
72    if ($self->listen) {
73        my $old_umask = umask;
74        unless ( $self->leave_umask ) {
75            umask(0);
76        }
77        $sock = FCGI::OpenSocket( $self->listen, 100 )
78          or die "failed to open FastCGI socket; $!";
79        unless ( $self->leave_umask ) {
80            umask($old_umask);
81        }
82    }
83    elsif ( !RUNNING_IN_HELL ) {
84        -S STDIN
85          or die "STDIN is not a socket; specify a listen location";
86    }
87
88    my %env;
89    my $error = \*STDERR;    # send STDERR to the web server
90    $error = \*STDOUT                # send STDERR to stdout (a logfile)
91      if $self->keep_stderr;         # (if asked to)
92
93    my $request =
94      FCGI::Request( \*STDIN, \*STDOUT, $error, \%env, $sock,
95        ( $self->nointr ? 0 : &FCGI::FAIL_ACCEPT_ON_INTR ),
96      );
97
98    my $proc_manager;
99
100    if ($self->listen) {
101        $self->daemon_fork() if $self->detach;
102
103        if ( $self->manager ) {
104            Class::MOP::load_class($self->manager);
105            $proc_manager = $self->manager->new(
106                {
107                    n_processes => $self->nproc,
108                    pid_fname   => $self->pidfile,
109                }
110            );
111
112            # detach *before* the ProcManager inits
113            $self->daemon_detach() if $self->detach;
114
115            $proc_manager->pm_manage();
116        }
117        elsif ( $self->detach ) {
118            $self->daemon_detach();
119        }
120    }
121
122    while ( $request->Accept >= 0 ) {
123        $proc_manager && $proc_manager->pm_pre_dispatch();
124
125        # If we're running under Lighttpd, swap PATH_INFO and SCRIPT_NAME
126        # http://lists.rawmode.org/pipermail/catalyst/2006-June/008361.html
127        # Thanks to Mark Blythe for this fix
128        if ( $env{SERVER_SOFTWARE} && $env{SERVER_SOFTWARE} =~ /lighttpd/ ) {
129            $env{PATH_INFO} ||= delete $env{SCRIPT_NAME};
130        }
131
132        $self->handle_request(
133            _connection => {
134                input_handle  => *STDIN,
135                output_handle => *STDOUT,
136                env           => \%env,
137            },
138        );
139
140        $proc_manager && $proc_manager->pm_post_dispatch();
141    }
142}
143
144sub daemon_fork {
145    require POSIX;
146    fork && exit;
147}
148
149sub daemon_detach {
150    my $self = shift;
151    print "FastCGI daemon started (pid $$)\n";
152    open STDIN,  "+</dev/null" or die $!; ## no critic
153    open STDOUT, ">&STDIN"     or die $!;
154    open STDERR, ">&STDIN"     or die $!;
155    POSIX::setsid();
156}
157
158__INTERFACE__
159
160__END__
161
162=for stopwords nointr pidfile nproc
163
164=head1 NAME
165
166HTTP::Engine::Interface::FCGI - FastCGI interface for HTTP::Engine
167
168=head1 ATTRIBUTES
169
170=over 4
171
172=item leave_umask
173
174=item keep_stderr
175
176=item nointr
177
178=item detach
179
180=item manager
181
182=item nproc
183
184=item pidfile
185
186=item listen
187
188=back
189
190=head1 AUTHORS
191
192Tokuhiro Matsuno
193
194=head1 THANKS TO
195
196many codes copied from L<Catalyst::Engine::FastCGI>. thanks authors of C::E::FastCGI!
197
Note: See TracBrowser for help on using the browser.