]> Sergey Matveev's repositories - public-inbox.git/commitdiff
www: cgit: fall back to WwwCoderepo on 404s
authorEric Wong <e@80x24.org>
Wed, 5 Oct 2022 22:29:40 +0000 (22:29 +0000)
committerEric Wong <e@80x24.org>
Fri, 7 Oct 2022 07:27:26 +0000 (07:27 +0000)
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.

lib/PublicInbox/Cgit.pm
lib/PublicInbox/GitHTTPBackend.pm
lib/PublicInbox/Qspawn.pm

index 1112d9f8c1c93e93f86a44ba459151c8e01c18e3..298663c73d89f96a5ee72bc019992fc5422db238 100644 (file)
@@ -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;
index ba3a8f208949aeac9a67a3bf5e8bfaf24b54e217..61a1356048bfc735ed96cf9714f8257378042ff3 100644 (file)
@@ -1,4 +1,4 @@
-# Copyright (C) 2016-2021 all contributors <meta@public-inbox.org>
+# Copyright (C) all contributors <meta@public-inbox.org>
 # License: AGPL-3.0+ <https://www.gnu.org/licenses/agpl-3.0.txt>
 
 # 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;
index cea34fc3325409078c18417aa470ef70cb78410f..ef9db43e637d6c51113d0d04d1c1bd56e5b9b3fc 100644 (file)
@@ -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