Merge branch 'jn/gitweb-fastcgi'
* jn/gitweb-fastcgi: gitweb: Run in FastCGI mode if gitweb script has .fcgi extension gitweb: Add support for FastCGI, using CGI::Fast gitweb: Put all per-connection code in run() subroutine
This commit is contained in:
commit
a031d76eeb
@ -28,8 +28,12 @@ BEGIN {
|
|||||||
CGI->compile() if $ENV{'MOD_PERL'};
|
CGI->compile() if $ENV{'MOD_PERL'};
|
||||||
}
|
}
|
||||||
|
|
||||||
our $cgi = new CGI;
|
|
||||||
our $version = "++GIT_VERSION++";
|
our $version = "++GIT_VERSION++";
|
||||||
|
|
||||||
|
our ($my_url, $my_uri, $base_url, $path_info, $home_link);
|
||||||
|
sub evaluate_uri {
|
||||||
|
our $cgi;
|
||||||
|
|
||||||
our $my_url = $cgi->url();
|
our $my_url = $cgi->url();
|
||||||
our $my_uri = $cgi->url(-absolute => 1);
|
our $my_uri = $cgi->url(-absolute => 1);
|
||||||
|
|
||||||
@ -58,6 +62,10 @@ if ($path_info) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# target of the home link on top of all pages
|
||||||
|
our $home_link = $my_uri || "/";
|
||||||
|
}
|
||||||
|
|
||||||
# core git executable to use
|
# core git executable to use
|
||||||
# this can just be "git" if your webserver has a sensible PATH
|
# this can just be "git" if your webserver has a sensible PATH
|
||||||
our $GIT = "++GIT_BINDIR++/git";
|
our $GIT = "++GIT_BINDIR++/git";
|
||||||
@ -70,9 +78,6 @@ our $projectroot = "++GITWEB_PROJECTROOT++";
|
|||||||
# the number is relative to the projectroot
|
# the number is relative to the projectroot
|
||||||
our $project_maxdepth = "++GITWEB_PROJECT_MAXDEPTH++";
|
our $project_maxdepth = "++GITWEB_PROJECT_MAXDEPTH++";
|
||||||
|
|
||||||
# target of the home link on top of all pages
|
|
||||||
our $home_link = $my_uri || "/";
|
|
||||||
|
|
||||||
# string of the home link on top of all pages
|
# string of the home link on top of all pages
|
||||||
our $home_link_str = "++GITWEB_HOME_LINK_STR++";
|
our $home_link_str = "++GITWEB_HOME_LINK_STR++";
|
||||||
|
|
||||||
@ -566,6 +571,8 @@ sub filter_snapshot_fmts {
|
|||||||
!$known_snapshot_formats{$_}{'disabled'}} @fmts;
|
!$known_snapshot_formats{$_}{'disabled'}} @fmts;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
our ($GITWEB_CONFIG, $GITWEB_CONFIG_SYSTEM);
|
||||||
|
sub evaluate_gitweb_config {
|
||||||
our $GITWEB_CONFIG = $ENV{'GITWEB_CONFIG'} || "++GITWEB_CONFIG++";
|
our $GITWEB_CONFIG = $ENV{'GITWEB_CONFIG'} || "++GITWEB_CONFIG++";
|
||||||
our $GITWEB_CONFIG_SYSTEM = $ENV{'GITWEB_CONFIG_SYSTEM'} || "++GITWEB_CONFIG_SYSTEM++";
|
our $GITWEB_CONFIG_SYSTEM = $ENV{'GITWEB_CONFIG_SYSTEM'} || "++GITWEB_CONFIG_SYSTEM++";
|
||||||
# die if there are errors parsing config file
|
# die if there are errors parsing config file
|
||||||
@ -576,6 +583,7 @@ if (-e $GITWEB_CONFIG) {
|
|||||||
do $GITWEB_CONFIG_SYSTEM;
|
do $GITWEB_CONFIG_SYSTEM;
|
||||||
die $@ if $@;
|
die $@ if $@;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
# Get loadavg of system, to compare against $maxload.
|
# Get loadavg of system, to compare against $maxload.
|
||||||
# Currently it requires '/proc/loadavg' present to get loadavg;
|
# Currently it requires '/proc/loadavg' present to get loadavg;
|
||||||
@ -600,14 +608,17 @@ sub get_loadavg {
|
|||||||
}
|
}
|
||||||
|
|
||||||
# version of the core git binary
|
# version of the core git binary
|
||||||
|
our $git_version;
|
||||||
|
sub evaluate_git_version {
|
||||||
our $git_version = qx("$GIT" --version) =~ m/git version (.*)$/ ? $1 : "unknown";
|
our $git_version = qx("$GIT" --version) =~ m/git version (.*)$/ ? $1 : "unknown";
|
||||||
$number_of_git_cmds++;
|
$number_of_git_cmds++;
|
||||||
|
}
|
||||||
|
|
||||||
$projects_list ||= $projectroot;
|
sub check_loadavg {
|
||||||
|
|
||||||
if (defined $maxload && get_loadavg() > $maxload) {
|
if (defined $maxload && get_loadavg() > $maxload) {
|
||||||
die_error(503, "The load average on the server is too high");
|
die_error(503, "The load average on the server is too high");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
# ======================================================================
|
# ======================================================================
|
||||||
# input validation and dispatch
|
# input validation and dispatch
|
||||||
@ -693,6 +704,9 @@ our %allowed_options = (
|
|||||||
# should be single values, but opt can be an array. We should probably
|
# should be single values, but opt can be an array. We should probably
|
||||||
# build an array of parameters that can be multi-valued, but since for the time
|
# build an array of parameters that can be multi-valued, but since for the time
|
||||||
# being it's only this one, we just single it out
|
# being it's only this one, we just single it out
|
||||||
|
sub evaluate_query_params {
|
||||||
|
our $cgi;
|
||||||
|
|
||||||
while (my ($name, $symbol) = each %cgi_param_mapping) {
|
while (my ($name, $symbol) = each %cgi_param_mapping) {
|
||||||
if ($symbol eq 'opt') {
|
if ($symbol eq 'opt') {
|
||||||
$input_params{$name} = [ $cgi->param($symbol) ];
|
$input_params{$name} = [ $cgi->param($symbol) ];
|
||||||
@ -700,6 +714,7 @@ while (my ($name, $symbol) = each %cgi_param_mapping) {
|
|||||||
$input_params{$name} = $cgi->param($symbol);
|
$input_params{$name} = $cgi->param($symbol);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
# now read PATH_INFO and update the parameter list for missing parameters
|
# now read PATH_INFO and update the parameter list for missing parameters
|
||||||
sub evaluate_path_info {
|
sub evaluate_path_info {
|
||||||
@ -844,8 +859,11 @@ sub evaluate_path_info {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
evaluate_path_info();
|
|
||||||
|
|
||||||
|
our ($action, $project, $file_name, $file_parent, $hash, $hash_parent, $hash_base,
|
||||||
|
$hash_parent_base, @extra_options, $page, $searchtype, $search_use_regexp,
|
||||||
|
$searchtext, $search_regexp);
|
||||||
|
sub evaluate_and_validate_params {
|
||||||
our $action = $input_params{'action'};
|
our $action = $input_params{'action'};
|
||||||
if (defined $action) {
|
if (defined $action) {
|
||||||
if (!validate_action($action)) {
|
if (!validate_action($action)) {
|
||||||
@ -943,11 +961,16 @@ if (defined $searchtext) {
|
|||||||
}
|
}
|
||||||
$search_regexp = $search_use_regexp ? $searchtext : quotemeta $searchtext;
|
$search_regexp = $search_use_regexp ? $searchtext : quotemeta $searchtext;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
# path to the current git repository
|
# path to the current git repository
|
||||||
our $git_dir;
|
our $git_dir;
|
||||||
$git_dir = "$projectroot/$project" if $project;
|
sub evaluate_git_dir {
|
||||||
|
our $git_dir = "$projectroot/$project" if $project;
|
||||||
|
}
|
||||||
|
|
||||||
|
our (@snapshot_fmts, $git_avatar);
|
||||||
|
sub configure_gitweb_features {
|
||||||
# list of supported snapshot formats
|
# list of supported snapshot formats
|
||||||
our @snapshot_fmts = gitweb_get_feature('snapshot');
|
our @snapshot_fmts = gitweb_get_feature('snapshot');
|
||||||
@snapshot_fmts = filter_snapshot_fmts(@snapshot_fmts);
|
@snapshot_fmts = filter_snapshot_fmts(@snapshot_fmts);
|
||||||
@ -964,6 +987,7 @@ if ($git_avatar eq 'gravatar') {
|
|||||||
} else {
|
} else {
|
||||||
$git_avatar = '';
|
$git_avatar = '';
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
# custom error handler: 'die <message>' is Internal Server Error
|
# custom error handler: 'die <message>' is Internal Server Error
|
||||||
sub handle_errors_html {
|
sub handle_errors_html {
|
||||||
@ -981,6 +1005,7 @@ sub handle_errors_html {
|
|||||||
set_message(\&handle_errors_html);
|
set_message(\&handle_errors_html);
|
||||||
|
|
||||||
# dispatch
|
# dispatch
|
||||||
|
sub dispatch {
|
||||||
if (!defined $action) {
|
if (!defined $action) {
|
||||||
if (defined $hash) {
|
if (defined $hash) {
|
||||||
$action = git_get_type($hash);
|
$action = git_get_type($hash);
|
||||||
@ -1000,8 +1025,89 @@ if ($action !~ m/^(?:opml|project_list|project_index)$/ &&
|
|||||||
die_error(400, "Project needed");
|
die_error(400, "Project needed");
|
||||||
}
|
}
|
||||||
$actions{$action}->();
|
$actions{$action}->();
|
||||||
|
}
|
||||||
|
|
||||||
|
sub run_request {
|
||||||
|
our $t0 = [Time::HiRes::gettimeofday()]
|
||||||
|
if defined $t0;
|
||||||
|
|
||||||
|
evaluate_uri();
|
||||||
|
evaluate_gitweb_config();
|
||||||
|
evaluate_git_version();
|
||||||
|
check_loadavg();
|
||||||
|
|
||||||
|
# $projectroot and $projects_list might be set in gitweb config file
|
||||||
|
$projects_list ||= $projectroot;
|
||||||
|
|
||||||
|
evaluate_query_params();
|
||||||
|
evaluate_path_info();
|
||||||
|
evaluate_and_validate_params();
|
||||||
|
evaluate_git_dir();
|
||||||
|
|
||||||
|
configure_gitweb_features();
|
||||||
|
|
||||||
|
dispatch();
|
||||||
|
}
|
||||||
|
|
||||||
|
our $is_last_request = sub { 1 };
|
||||||
|
our ($pre_dispatch_hook, $post_dispatch_hook, $pre_listen_hook);
|
||||||
|
our $CGI = 'CGI';
|
||||||
|
our $cgi;
|
||||||
|
sub configure_as_fcgi {
|
||||||
|
require CGI::Fast;
|
||||||
|
our $CGI = 'CGI::Fast';
|
||||||
|
|
||||||
|
my $request_number = 0;
|
||||||
|
# let each child service 100 requests
|
||||||
|
our $is_last_request = sub { ++$request_number > 100 };
|
||||||
|
}
|
||||||
|
sub evaluate_argv {
|
||||||
|
my $script_name = $ENV{'SCRIPT_NAME'} || $ENV{'SCRIPT_FILENAME'} || __FILE__;
|
||||||
|
configure_as_fcgi()
|
||||||
|
if $script_name =~ /\.fcgi$/;
|
||||||
|
|
||||||
|
return unless (@ARGV);
|
||||||
|
|
||||||
|
require Getopt::Long;
|
||||||
|
Getopt::Long::GetOptions(
|
||||||
|
'fastcgi|fcgi|f' => \&configure_as_fcgi,
|
||||||
|
'nproc|n=i' => sub {
|
||||||
|
my ($arg, $val) = @_;
|
||||||
|
return unless eval { require FCGI::ProcManager; 1; };
|
||||||
|
my $proc_manager = FCGI::ProcManager->new({
|
||||||
|
n_processes => $val,
|
||||||
|
});
|
||||||
|
our $pre_listen_hook = sub { $proc_manager->pm_manage() };
|
||||||
|
our $pre_dispatch_hook = sub { $proc_manager->pm_pre_dispatch() };
|
||||||
|
our $post_dispatch_hook = sub { $proc_manager->pm_post_dispatch() };
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
sub run {
|
||||||
|
evaluate_argv();
|
||||||
|
|
||||||
|
$pre_listen_hook->()
|
||||||
|
if $pre_listen_hook;
|
||||||
|
|
||||||
|
REQUEST:
|
||||||
|
while ($cgi = $CGI->new()) {
|
||||||
|
$pre_dispatch_hook->()
|
||||||
|
if $pre_dispatch_hook;
|
||||||
|
|
||||||
|
run_request();
|
||||||
|
|
||||||
|
$pre_dispatch_hook->()
|
||||||
|
if $post_dispatch_hook;
|
||||||
|
|
||||||
|
last REQUEST if ($is_last_request->());
|
||||||
|
}
|
||||||
|
|
||||||
DONE_GITWEB:
|
DONE_GITWEB:
|
||||||
1;
|
1;
|
||||||
|
}
|
||||||
|
|
||||||
|
run();
|
||||||
|
|
||||||
## ======================================================================
|
## ======================================================================
|
||||||
## action links
|
## action links
|
||||||
|
Loading…
Reference in New Issue
Block a user