From: Eric Wong Date: Wed, 5 Oct 2022 22:29:40 +0000 (+0000) Subject: www: cgit: fall back to WwwCoderepo on 404s X-Git-Url: http://www.git.stargrave.org/?p=public-inbox.git;a=commitdiff_plain;h=26037c85f73de67197af1987e4c0fa4786ac1e31 www: cgit: fall back to WwwCoderepo on 404s We can't rely on 3-element array response when calling WwwCoderepo for ViewVCS endpoints since that uses Qspawn internally. Thus, we have to allow two Qspawn objects to run in parallel and ensure `qspawn.wcb' only gets called once, so we end up duplicating the entire $ctx to ensure this. --- diff --git a/lib/PublicInbox/Cgit.pm b/lib/PublicInbox/Cgit.pm index 1112d9f8..298663c7 100644 --- a/lib/PublicInbox/Cgit.pm +++ b/lib/PublicInbox/Cgit.pm @@ -83,7 +83,7 @@ my @PASS_ENV = qw( my $parse_cgi_headers = \&PublicInbox::GitHTTPBackend::parse_cgi_headers; sub call { - my ($self, $env) = @_; + my ($self, $env, $ctx) = @_; # $ctx is optional, used by WWW my $path_info = $env->{PATH_INFO}; my $cgit_data; @@ -109,7 +109,7 @@ sub call { my $rdr = input_prepare($env) or return r(500); my $qsp = PublicInbox::Qspawn->new($self->{cmd}, $cgi_env, $rdr); my $limiter = $self->{pi_cfg}->limiter('-cgit'); - $qsp->psgi_return($env, $limiter, $parse_cgi_headers); + $qsp->psgi_return($env, $limiter, $parse_cgi_headers, $ctx); } 1; diff --git a/lib/PublicInbox/GitHTTPBackend.pm b/lib/PublicInbox/GitHTTPBackend.pm index ba3a8f20..61a13560 100644 --- a/lib/PublicInbox/GitHTTPBackend.pm +++ b/lib/PublicInbox/GitHTTPBackend.pm @@ -1,4 +1,4 @@ -# Copyright (C) 2016-2021 all contributors +# Copyright (C) all contributors # License: AGPL-3.0+ # when no endpoints match, fallback to this and serve a static file @@ -132,7 +132,7 @@ sub input_prepare { } sub parse_cgi_headers { - my ($r, $bref) = @_; + my ($r, $bref, $ctx) = @_; return r(500) unless defined $r && $r >= 0; $$bref =~ s/\A(.*?)\r?\n\r?\n//s or return $r == 0 ? r(500) : undef; my $h = $1; @@ -146,7 +146,20 @@ sub parse_cgi_headers { push @h, $k, $v; } } - [ $code, \@h ] + + # fallback to WwwCoderepo if cgit 404s. Duplicating $ctx prevents + # ->finalize from the current Qspawn from using qspawn.wcb + if ($code == 404 && $ctx->{www} && !$ctx->{_coderepo_tried}++) { + my %ctx = %$ctx; + $ctx{env} = +{ %{$ctx->{env}} }; + delete $ctx->{env}->{'qspawn.wcb'}; + $ctx->{env}->{'plack.skip-deflater'} = 1; # prevent 2x gzip + my $res = $ctx->{www}->coderepo->srv(\%ctx); + $res->(delete $ctx{env}->{'qspawn.wcb'}) if ref($res) eq 'CODE'; + $res; # non ARRAY ref for ->psgi_return_init_cb + } else { + [ $code, \@h ] + } } 1; diff --git a/lib/PublicInbox/Qspawn.pm b/lib/PublicInbox/Qspawn.pm index cea34fc3..ef9db43e 100644 --- a/lib/PublicInbox/Qspawn.pm +++ b/lib/PublicInbox/Qspawn.pm @@ -225,19 +225,19 @@ sub psgi_return_init_cb { my ($self) = @_; my $r = rd_hdr($self) or return; my $env = $self->{psgi_env}; - my $filter = delete $env->{'qspawn.filter'} // - PublicInbox::GzipFilter::qsp_maybe($r->[1], $env); + my $filter = delete($env->{'qspawn.filter'}) // (ref($r) eq 'ARRAY' ? + PublicInbox::GzipFilter::qsp_maybe($r->[1], $env) : undef); my $wcb = delete $env->{'qspawn.wcb'}; my $async = delete $self->{async}; # PublicInbox::HTTPD::Async - if (scalar(@$r) == 3) { # error + if (ref($r) ne 'ARRAY' || scalar(@$r) == 3) { # error if ($async) { # calls rpipe->close && ->event_step $async->close; # PublicInbox::HTTPD::Async::close } else { $self->{rpipe}->close; event_step($self); } - $wcb->($r); + $wcb->($r) if ref($r) eq 'ARRAY'; } elsif ($async) { # done reading headers, handoff to read body my $fh = $wcb->($r); # scalar @$r == 2