From 8bbc156ca9a4bf3bfff8a9b7014a002808b1b7f0 Mon Sep 17 00:00:00 2001 From: Frédéric Buclin Date: Wed, 23 Dec 2015 20:46:43 +0100 Subject: Bug 1201113: Support to run Bugzilla as a PSGI application r=dylan --- Bugzilla/CGI.pm | 5 +++-- Bugzilla/Config.pm | 21 ++++++++++++--------- Bugzilla/Error.pm | 5 +++-- Bugzilla/Install/Filesystem.pm | 1 + Bugzilla/Install/Requirements.pm | 21 +++++++++++++++++++++ Bugzilla/Install/Util.pm | 10 ++++++++++ Bugzilla/Template.pm | 4 ++-- 7 files changed, 52 insertions(+), 15 deletions(-) (limited to 'Bugzilla') diff --git a/Bugzilla/CGI.pm b/Bugzilla/CGI.pm index fcca0ec6a..25ee0acbe 100644 --- a/Bugzilla/CGI.pm +++ b/Bugzilla/CGI.pm @@ -66,7 +66,7 @@ sub new { # else we will be redirected outside Bugzilla. my $script_name = $self->script_name; $path_info =~ s/^\Q$script_name\E//; - if ($path_info) { + if ($script_name && $path_info) { print $self->redirect($self->url(-path => 0, -query => 1)); } } @@ -283,7 +283,7 @@ sub close_standby_message { print $self->multipart_end(); print $self->multipart_start(-type => $contenttype); } - else { + elsif (!$self->{_header_done}) { print $self->header($contenttype); } } @@ -356,6 +356,7 @@ sub header { Bugzilla::Hook::process('cgi_headers', { cgi => $self, headers => \%headers } ); + $self->{_header_done} = 1; return $self->SUPER::header(%headers) || ""; } diff --git a/Bugzilla/Config.pm b/Bugzilla/Config.pm index 5dfe2e37d..d47577212 100644 --- a/Bugzilla/Config.pm +++ b/Bugzilla/Config.pm @@ -16,6 +16,7 @@ use autodie qw(:default); use Bugzilla::Constants; use Bugzilla::Hook; +use Bugzilla::Install::Util qw(i_am_persistent); use Bugzilla::Util qw(trick_taint); use JSON::XS; @@ -319,15 +320,17 @@ sub read_param_file { } } elsif ($ENV{'SERVER_SOFTWARE'}) { - # We're in a CGI, but the params file doesn't exist. We can't - # Template Toolkit, or even install_string, since checksetup - # might not have thrown an error. Bugzilla::CGI->new - # hasn't even been called yet, so we manually use CGI::Carp here - # so that the user sees the error. - require CGI::Carp; - CGI::Carp->import('fatalsToBrowser'); - die "The $file file does not exist." - . ' You probably need to run checksetup.pl.', + # We're in a CGI, but the params file doesn't exist. We can't + # Template Toolkit, or even install_string, since checksetup + # might not have thrown an error. Bugzilla::CGI->new + # hasn't even been called yet, so we manually use CGI::Carp here + # so that the user sees the error. + unless (i_am_persistent()) { + require CGI::Carp; + CGI::Carp->import('fatalsToBrowser'); + } + die "The $file file does not exist." + . ' You probably need to run checksetup.pl.', } return \%params; } diff --git a/Bugzilla/Error.pm b/Bugzilla/Error.pm index e730022db..ee40ccf8b 100644 --- a/Bugzilla/Error.pm +++ b/Bugzilla/Error.pm @@ -28,8 +28,9 @@ use Date::Format; sub _in_eval { my $in_eval = 0; for (my $stack = 1; my $sub = (caller($stack))[3]; $stack++) { - last if $sub =~ /^ModPerl/; - $in_eval = 1 if $sub =~ /^\(eval\)/; + last if $sub =~ /^(?:ModPerl|Plack|CGI::Compile)/; + # An eval followed by CGI::Compile is not a "real" eval. + $in_eval = 1 if $sub =~ /^\(eval\)/ && (caller($stack + 1))[3] !~ /^CGI::Compile/; } return $in_eval; } diff --git a/Bugzilla/Install/Filesystem.pm b/Bugzilla/Install/Filesystem.pm index 5f5677460..e17285b2f 100644 --- a/Bugzilla/Install/Filesystem.pm +++ b/Bugzilla/Install/Filesystem.pm @@ -167,6 +167,7 @@ sub FILESYSTEM { 'install-module.pl' => { perms => OWNER_EXECUTE }, 'clean-bug-user-last-visit.pl' => { perms => WS_EXECUTE }, + 'app.psgi' => { perms => CGI_READ }, 'Bugzilla.pm' => { perms => CGI_READ }, "$localconfig*" => { perms => CGI_READ }, 'bugzilla.dtd' => { perms => WS_SERVE }, diff --git a/Bugzilla/Install/Requirements.pm b/Bugzilla/Install/Requirements.pm index 9a03968d7..a48778c1b 100644 --- a/Bugzilla/Install/Requirements.pm +++ b/Bugzilla/Install/Requirements.pm @@ -312,6 +312,26 @@ sub OPTIONAL_MODULES { version => 0, feature => ['jsonrpc'], }, + { + package => 'Plack', + module => 'Plack', + # 1.0031 contains a security fix which would affect us. + # It also fixes warnings thrown in Perl 5.20 and newer. + version => 1.0031, + feature => ['psgi'], + }, + { + package => 'CGI-Compile', + module => 'CGI::Compile', + version => 0, + feature => ['psgi'], + }, + { + package => 'CGI-Emulate-PSGI', + module => 'CGI::Emulate::PSGI', + version => 0, + feature => ['psgi'], + }, { package => 'Test-Taint', module => 'Test::Taint', @@ -474,6 +494,7 @@ use constant FEATURE_FILES => ( 'Bugzilla/WebService.pm', 'Bugzilla/WebService/*.pm'], rest => ['Bugzilla/WebService/Server/REST.pm', 'rest.cgi', 'Bugzilla/WebService/Server/REST/Resources/*.pm'], + psgi => ['app.psgi'], moving => ['importxml.pl'], auth_ldap => ['Bugzilla/Auth/Verify/LDAP.pm'], auth_radius => ['Bugzilla/Auth/Verify/RADIUS.pm'], diff --git a/Bugzilla/Install/Util.pm b/Bugzilla/Install/Util.pm index c05037061..82752b961 100644 --- a/Bugzilla/Install/Util.pm +++ b/Bugzilla/Install/Util.pm @@ -34,6 +34,7 @@ our @EXPORT_OK = qw( extension_requirement_packages extension_template_directory extension_web_directory + i_am_persistent indicate_progress install_string include_languages @@ -83,6 +84,10 @@ sub get_version_and_os { os_ver => $os_details[3] }; } +sub i_am_persistent { + return ($ENV{MOD_PERL} || $ENV{BZ_PLACK}) ? 1 : 0; +} + sub _extension_paths { my $dir = bz_locations()->{'extensionsdir'}; my @extension_items = glob("$dir/*"); @@ -711,6 +716,11 @@ binary, if the binary is in the C. Returns a hash containing information about what version of Bugzilla we're running, what perl version we're using, and what OS we're running on. +=item C + +Returns true if Bugzilla is running in a persistent environment, such as +mod_perl or PSGI. Returns false if running in mod_cgi mode. + =item C Returns the language to use based on the LC_CTYPE value returned by the OS. diff --git a/Bugzilla/Template.pm b/Bugzilla/Template.pm index 04abe8200..9398ca4b5 100644 --- a/Bugzilla/Template.pm +++ b/Bugzilla/Template.pm @@ -17,7 +17,7 @@ use Bugzilla::WebService::Constants; use Bugzilla::Hook; use Bugzilla::Install::Requirements; use Bugzilla::Install::Util qw(install_string template_include_path - include_languages); + include_languages i_am_persistent); use Bugzilla::Classification; use Bugzilla::Keyword; use Bugzilla::Util; @@ -740,7 +740,7 @@ sub create { # if a packager has modified bz_locations() to contain absolute # paths. ABSOLUTE => 1, - RELATIVE => $ENV{MOD_PERL} ? 0 : 1, + RELATIVE => i_am_persistent() ? 0 : 1, COMPILE_DIR => bz_locations()->{'template_cache'}, -- cgit v1.2.3-24-g4f1b