import rt 3.8.10
[freeside.git] / rt / bin / fastcgi_server.in
1 #!@PERL@
2 # BEGIN BPS TAGGED BLOCK {{{
3 #
4 # COPYRIGHT:
5 #
6 # This software is Copyright (c) 1996-2011 Best Practical Solutions, LLC
7 #                                          <sales@bestpractical.com>
8 #
9 # (Except where explicitly superseded by other copyright notices)
10 #
11 #
12 # LICENSE:
13 #
14 # This work is made available to you under the terms of Version 2 of
15 # the GNU General Public License. A copy of that license should have
16 # been provided with this software, but in any event can be snarfed
17 # from www.gnu.org.
18 #
19 # This work is distributed in the hope that it will be useful, but
20 # WITHOUT ANY WARRANTY; without even the implied warranty of
21 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
22 # General Public License for more details.
23 #
24 # You should have received a copy of the GNU General Public License
25 # along with this program; if not, write to the Free Software
26 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
27 # 02110-1301 or visit their web page on the internet at
28 # http://www.gnu.org/licenses/old-licenses/gpl-2.0.html.
29 #
30 #
31 # CONTRIBUTION SUBMISSION POLICY:
32 #
33 # (The following paragraph is not intended to limit the rights granted
34 # to you to modify and distribute this software under the terms of
35 # the GNU General Public License and is only of importance to you if
36 # you choose to contribute your changes and enhancements to the
37 # community by submitting them to Best Practical Solutions, LLC.)
38 #
39 # By intentionally submitting any modifications, corrections or
40 # derivatives to this work, or any other work intended for use with
41 # Request Tracker, to Best Practical Solutions, LLC, you confirm that
42 # you are the copyright holder for those contributions and you grant
43 # Best Practical Solutions,  LLC a nonexclusive, worldwide, irrevocable,
44 # royalty-free, perpetual, license to use, copy, create derivative
45 # works based on those contributions, and sublicense and distribute
46 # those contributions and any derivatives thereof.
47 #
48 # END BPS TAGGED BLOCK }}}
49 =head1 NAME
50
51 fastcgi_server - external FastCGI server for RT
52
53 =head1 USAGE
54
55     # get help
56     fastcgi_server -h
57
58     # start a server using defaults
59     fastcgi_server
60
61     # start server with custom option
62     fastcgi_server --socket /path/to/socket -n 5
63     fastcgi_server --port 12345 -n 5
64
65 =head1 DESCRIPTION
66
67 This is a forking external FastCGI server for RT, it can be used
68 with apache and other servers supporting FastCGI technology.
69
70 An advantage is lower memory usage because of sharing memory
71 between process. It's easier to setup this with nginx and other
72 servers that can not maintain pool of fastcgi servers, apache
73 can do this.
74
75 Disadvantage is that you have to start this server yourself and
76 monitor it, web servers wouldn't be able to restart it on crash.
77
78 =head1 OPTIONS
79
80 =over 4
81
82 =item -h, --help - get help
83
84 =item -n, --nprocesses - number of processes to start, by default 10
85
86 =item -s, --socket - socket path, by default F<RT/var/path/fastcgi.sock>
87 usually F</opt/rt3/var/fastcgi.sock>.
88
89 =item -p, --port - port to use instead of socket, by default socket is
90 used.
91
92 =item --pidfile - pid file path, by default F<RT/var/path/fastcgi.pid>.
93
94 =back
95
96 =head1 SERVER CONFIGURATION
97
98 =head2 nginx
99
100 Below you can find example of minimal config for nginx to run RT
101 with this FastCGI server. It's not ideal, but a good enough start.
102
103     worker_processes  1;
104     events { worker_connections  1024; }
105
106     pid         /opt/rt3/var/nginx/server.pid;
107     error_log   /opt/rt3/var/nginx/error.log debug;
108
109     http {
110         access_log  /opt/rt3/var/nginx/access.log;
111
112         server {
113             listen       8080;
114             server_name  localhost;
115
116             location / {
117                 root           /opt/rt3/share/html;
118                 fastcgi_pass   unix:/opt/rt3/var/fastcgi.sock;
119
120                 fastcgi_param  QUERY_STRING       $query_string;
121                 fastcgi_param  REQUEST_METHOD     $request_method;
122                 fastcgi_param  CONTENT_TYPE       $content_type;
123                 fastcgi_param  CONTENT_LENGTH     $content_length;
124                 fastcgi_param  PATH_INFO          $fastcgi_script_name;
125             }
126
127             location /NoAuth/images/ {
128                 alias   /opt/rt3/share/html/NoAuth/images/;
129             }
130         }
131     }
132
133 =head1 lighttpd
134
135 Server config:
136
137     server.name = "localhost"
138     server.port = 80
139
140     server.username  = "rt_web_user"
141     server.groupname = "rt_web_group"
142
143     server.pid-file = "/opt/rt3/var/lighthttpd/server.pid"
144     server.errorlog = "/opt/rt3/var/lighthttpd/error.log"
145
146     server.document-root = "/opt/rt3/share/html"
147
148     server.modules = ( "mod_fastcgi" )
149     fastcgi.server = (
150         "/" => ((
151             "socket" => "/opt/rt3/var/fastcgi.sock",
152             "check-local" => "disable",
153             "fix-root-scriptname" => "enable",
154         ))
155     )
156
157 =cut
158
159
160 use strict;
161 use warnings;
162 no warnings qw(once);
163
164 package RT::Interface::Web::FCGI::Server;
165 use base qw(FCGI::ProcManager);
166
167 package main;
168
169 use Getopt::Long;
170
171 my %opt = (
172     help       => 0,
173     socket     => '',
174     port       => 0,
175     nprocesses => 10,
176     pidfile    => '',
177 );
178
179 GetOptions(
180     'h|help!'        => \$opt{'help'},
181     's|socket=s'     => \$opt{'socket'},
182     'p|port=s'       => \$opt{'port'},
183     'n|nprocesses=s' => \$opt{'nprocesses'},
184     'pidfile=s'      => \$opt{'pidfile'},
185 );
186
187 if ( $opt{'help'} ) {
188     require Pod::Usage;
189     Pod::Usage::pod2usage(
190         -message => "",
191         -exitval => $opt{'help'}? 0 : 1,
192         -verbose => 99,
193         -sections => $opt{'help'}? 'NAME|USAGE|DESCRIPTION|OPTIONS' : 'NAME|USAGE',
194     );
195 }
196
197 $ENV{'RT_WEBMUX_HEAVY_LOAD'} = 1;
198 use File::Basename;
199 require (dirname(__FILE__) .'/webmux.pl');
200
201 unless ( $opt{'socket'} || $opt{'port'} ) {
202     require File::Spec;
203     $opt{'socket'} = File::Spec->catfile($RT::VarPath, 'fastcgi.sock');
204 }
205 elsif ( $opt{'port'} ) {
206     $opt{'socket'} = ':'. $opt{'port'};
207 }
208 $ENV{'FCGI_SOCKET_PATH'} = $opt{'socket'};
209
210 $opt{'pidfile'} ||= File::Spec->catfile($RT::VarPath, 'fastcgi.pid');
211
212 require CGI::Fast;
213
214 my $proc_manager = RT::Interface::Web::FCGI::Server->new({
215     n_processes => $opt{'nprocesses'} || 10,
216     pid_fname   => $opt{'pidfile'},
217 });
218
219 $proc_manager->pm_manage();
220
221 while ( my $cgi = CGI::Fast->new ) {
222     $proc_manager->pm_pre_dispatch;
223
224     $ENV{'PATH'}   = '/bin:/usr/bin';
225     $ENV{'CDPATH'} = '' if defined $ENV{'CDPATH'};
226     $ENV{'SHELL'}  = '/bin/sh' if defined $ENV{'SHELL'};
227     $ENV{'ENV'}    = '' if defined $ENV{'ENV'};
228     $ENV{'IFS'}    = '' if defined $ENV{'IFS'};
229
230     Module::Refresh->refresh if RT->Config->Get('DevelMode');
231     RT::ConnectToDatabase();
232
233     # Each environment has its own way of handling .. and so on in paths,
234     # so RT consistently forbids such paths.
235     if ( $cgi->path_info =~ m{/\.} ) {
236         $RT::Logger->crit("Invalid request for ".$cgi->path_info." aborting");
237         print STDOUT "HTTP/1.0 400\r\n\r\n";
238
239         RT::Interface::Web::Handler->CleanupRequest();
240         $proc_manager->pm_post_dispatch;
241
242         next;
243     }
244
245     my $interp = $RT::Mason::Handler->interp;
246     if (
247         !$interp->comp_exists( $cgi->path_info )
248         && $interp->comp_exists( $cgi->path_info . "/index.html" )
249     ) {
250         $cgi->path_info( $cgi->path_info . "/index.html" );
251     }
252
253     local $@;
254     eval { $RT::Mason::Handler->handle_cgi_object($cgi); };
255     if ($@) {
256         $RT::Logger->crit($@);
257     }
258     RT::Interface::Web::Handler->CleanupRequest;
259
260     $proc_manager->pm_post_dispatch;
261 }
262
263 1;