From 46fd93bff2dcbf2eded0b9b849b72c0982449ea9 Mon Sep 17 00:00:00 2001 From: David Cook Date: Wed, 1 Dec 2021 01:31:27 +0000 Subject: [PATCH] Bug 29420: HTTP status code incorrect when calling error pages directly under Plack/PSGI The error pages wrote a HTTP status code of 200 for all PSGI requests, even though it should have only done it for PSGI requests from the ErrorDocument middleware. This patch fixes that. 0) Do not apply patch 1) Open F12 dev tools and go to Network tab 2) Go to http://localhost:8081/files/blah 3) Note that the webpage is a 404 error but HTTP status code is 200 4) Go to http://localhost:8081/cgi-bin/koha/circ/blah 5) Note that the webpage is a 404 error and HTTP status code is 404 6) Apply patch 7) Go to http://localhost:8081/files/blah 8) Note that the webpage is a 404 error and HTTP status code is 404 9) Go to http://localhost:8081/cgi-bin/koha/circ/blah 10) Note that the webpage is a 404 error and HTTP status code is 404 --- C4/Context.pm | 34 ++++++++++++++++++++++++++++++++++ errors/400.pl | 2 +- errors/401.pl | 2 +- errors/402.pl | 2 +- errors/403.pl | 2 +- errors/404.pl | 2 +- errors/500.pl | 2 +- opac/errors/400.pl | 2 +- opac/errors/401.pl | 2 +- opac/errors/402.pl | 2 +- opac/errors/403.pl | 2 +- opac/errors/404.pl | 2 +- opac/errors/500.pl | 2 +- 13 files changed, 46 insertions(+), 12 deletions(-) diff --git a/C4/Context.pm b/C4/Context.pm index 241589e7b5..b42f933b08 100644 --- a/C4/Context.pm +++ b/C4/Context.pm @@ -42,6 +42,7 @@ use File::Spec; use POSIX; use YAML::XS; use ZOOM; +use List::MoreUtils qw(any); use Koha::Caches; use Koha::Config::SysPref; @@ -978,6 +979,39 @@ sub needs_install { return ($self->preference('Version')) ? 0 : 1; } +=head3 is_psgi_or_plack + +is_psgi_or_plack returns true if there is an environmental variable +prefixed with "psgi" or "plack". This is useful for detecting whether +this is a PSGI app or a CGI app, and implementing code as appropriate. + +=cut + +sub is_psgi_or_plack { + my $is_psgi_or_plack = 0; + if ( any { /(^psgi\.|^plack\.)/i } keys %ENV ) { + $is_psgi_or_plack = 1; + } + return $is_psgi_or_plack; +} + +=head3 is_internal_PSGI_request + +is_internal_PSGI_request is used to detect if this request was made +from within the individual PSGI app or externally from the mounted PSGI +app + +=cut + +#NOTE: This is not a very robust method but it's the best we have so far +sub is_internal_PSGI_request { + my $is_internal = 0; + if ( (__PACKAGE__->is_psgi_or_plack) && ( $ENV{REQUEST_URI} !~ /^(\/intranet|\/opac)/ ) ){ + $is_internal = 1; + } + return $is_internal; +} + __END__ =head1 ENVIRONMENT diff --git a/errors/400.pl b/errors/400.pl index e3cfc5e0bb..0bddd49fc8 100755 --- a/errors/400.pl +++ b/errors/400.pl @@ -38,7 +38,7 @@ $template->param ( errno => 400, ); my $status = '400 Bad Request'; -if ( any { /(^psgi\.|^plack\.)/i } keys %ENV ) { +if ( C4::Context->is_internal_PSGI_request() ) { $status = '200 OK'; } output_with_http_headers $query, $cookie, $template->output, 'html', $status; diff --git a/errors/401.pl b/errors/401.pl index 5cc3ac432d..f5761fcb35 100755 --- a/errors/401.pl +++ b/errors/401.pl @@ -37,7 +37,7 @@ $template->param ( errno => 401, ); my $status = '401 Unauthorized'; -if ( any { /(^psgi\.|^plack\.)/i } keys %ENV ) { +if ( C4::Context->is_internal_PSGI_request() ) { $status = '200 OK'; } output_with_http_headers $query, $cookie, $template->output, 'html', $status; diff --git a/errors/402.pl b/errors/402.pl index 0ffe905ef6..835aed3ea3 100755 --- a/errors/402.pl +++ b/errors/402.pl @@ -38,7 +38,7 @@ $template->param ( errno => 402, ); my $status = '402 Payment Required'; -if ( any { /(^psgi\.|^plack\.)/i } keys %ENV ) { +if ( C4::Context->is_internal_PSGI_request() ) { $status = '200 OK'; } output_with_http_headers $query, $cookie, $template->output, 'html', $status; diff --git a/errors/403.pl b/errors/403.pl index 1a45904f9d..33706a6f56 100755 --- a/errors/403.pl +++ b/errors/403.pl @@ -38,7 +38,7 @@ $template->param ( errno => 403, ); my $status = '403 Forbidden'; -if ( any { /(^psgi\.|^plack\.)/i } keys %ENV ) { +if ( C4::Context->is_internal_PSGI_request() ) { $status = '200 OK'; } output_with_http_headers $query, $cookie, $template->output, 'html', $status; diff --git a/errors/404.pl b/errors/404.pl index a784979154..049db4aa40 100755 --- a/errors/404.pl +++ b/errors/404.pl @@ -38,7 +38,7 @@ $template->param ( errno => 404, ); my $status = '404 Not Found'; -if ( any { /(^psgi\.|^plack\.)/i } keys %ENV ) { +if ( C4::Context->is_internal_PSGI_request() ) { $status = '200 OK'; } output_with_http_headers $query, $cookie, $template->output, 'html', $status; diff --git a/errors/500.pl b/errors/500.pl index df8940abc9..26dab6f93b 100755 --- a/errors/500.pl +++ b/errors/500.pl @@ -38,7 +38,7 @@ $template->param ( errno => 500, ); my $status = '500 Internal Server Error'; -if ( any { /(^psgi\.|^plack\.)/i } keys %ENV ) { +if ( C4::Context->is_internal_PSGI_request() ) { $status = '200 OK'; } output_with_http_headers $query, $cookie, $template->output, 'html', $status; diff --git a/opac/errors/400.pl b/opac/errors/400.pl index eb6609a8ae..7d3a63ca2d 100755 --- a/opac/errors/400.pl +++ b/opac/errors/400.pl @@ -38,7 +38,7 @@ $template->param ( errno => 400, ); my $status = '400 Bad Request'; -if ( any { /(^psgi\.|^plack\.)/i } keys %ENV ) { +if ( C4::Context->is_internal_PSGI_request() ) { $status = '200 OK'; } output_with_http_headers $query, $cookie, $template->output, 'html', $status; diff --git a/opac/errors/401.pl b/opac/errors/401.pl index 91fbc2dccc..abd65d72a6 100755 --- a/opac/errors/401.pl +++ b/opac/errors/401.pl @@ -38,7 +38,7 @@ $template->param ( errno => 401, ); my $status = '401 Unauthorized'; -if ( any { /(^psgi\.|^plack\.)/i } keys %ENV ) { +if ( C4::Context->is_internal_PSGI_request() ) { $status = '200 OK'; } output_with_http_headers $query, $cookie, $template->output, 'html', $status; diff --git a/opac/errors/402.pl b/opac/errors/402.pl index 682f39c7a5..3ba2d62b50 100755 --- a/opac/errors/402.pl +++ b/opac/errors/402.pl @@ -38,7 +38,7 @@ $template->param ( errno => 402, ); my $status = '402 Payment Required'; -if ( any { /(^psgi\.|^plack\.)/i } keys %ENV ) { +if ( C4::Context->is_internal_PSGI_request() ) { $status = '200 OK'; } output_with_http_headers $query, $cookie, $template->output, 'html', $status; diff --git a/opac/errors/403.pl b/opac/errors/403.pl index 0e38cdf836..ac3992fb6c 100755 --- a/opac/errors/403.pl +++ b/opac/errors/403.pl @@ -38,7 +38,7 @@ $template->param ( errno => 403, ); my $status = '403 Forbidden'; -if ( any { /(^psgi\.|^plack\.)/i } keys %ENV ) { +if ( C4::Context->is_internal_PSGI_request() ) { $status = '200 OK'; } output_with_http_headers $query, $cookie, $template->output, 'html', $status; diff --git a/opac/errors/404.pl b/opac/errors/404.pl index 1814e9da90..e07e056853 100755 --- a/opac/errors/404.pl +++ b/opac/errors/404.pl @@ -38,7 +38,7 @@ $template->param ( errno => 404, ); my $status = '404 Not Found'; -if ( any { /(^psgi\.|^plack\.)/i } keys %ENV ) { +if ( C4::Context->is_internal_PSGI_request() ) { $status = '200 OK'; } output_with_http_headers $query, $cookie, $template->output, 'html', $status; diff --git a/opac/errors/500.pl b/opac/errors/500.pl index 6918c1e62a..c25f848211 100755 --- a/opac/errors/500.pl +++ b/opac/errors/500.pl @@ -38,7 +38,7 @@ $template->param ( errno => 500, ); my $status = '500 Internal Server Error'; -if ( any { /(^psgi\.|^plack\.)/i } keys %ENV ) { +if ( C4::Context->is_internal_PSGI_request() ) { $status = '200 OK'; } output_with_http_headers $query, $cookie, $template->output, 'html', $status; -- 2.20.1