From 106fb9168baf42e7226fa496e3ba6936111d8629 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 Signed-off-by: Martin Renvoize Signed-off-by: Jonathan Druart --- 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 241589e7b57..b42f933b088 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 e3cfc5e0bb3..0bddd49fc87 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 5cc3ac432dc..f5761fcb354 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 0ffe905ef69..835aed3ea3b 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 1a45904f9dc..33706a6f568 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 a784979154f..049db4aa401 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 df8940abc9a..26dab6f93bb 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 eb6609a8ae8..7d3a63ca2dd 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 91fbc2dccc7..abd65d72a67 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 682f39c7a5f..3ba2d62b50b 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 0e38cdf8365..ac3992fb6cc 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 1814e9da908..e07e0568531 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 6918c1e62a9..c25f8482112 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.25.1