From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on dcvr.yhbt.net X-Spam-Level: X-Spam-ASN: X-Spam-Status: No, score=-4.2 required=3.0 tests=ALL_TRUSTED,BAYES_00, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF shortcircuit=no autolearn=ham autolearn_force=no version=3.4.2 Received: from localhost (dcvr.yhbt.net [127.0.0.1]) by dcvr.yhbt.net (Postfix) with ESMTP id 6D2951F51E for ; Wed, 5 Oct 2022 22:29:41 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=80x24.org; s=selector1; t=1665008981; bh=q95Xj5sH0LomS/ZCwcSufOGdPpep0v2YV651wsJYwtc=; h=From:To:Subject:Date:In-Reply-To:References:From; b=xeANbND9k0fMOA4uO7A8+lYxZj1ejWiBOujltyUPFWi6p+VQ2BGitH2YxuLZuhBSH Sc4hGiPssUQnGyqgYD6Cwm4vSnWgfaWWVwKy0/2gsqzzEIN6dJJqixlR67eaNTCycD VxVhqEnTVhelFRtBraZaZGxWnIJtAREDPMPi2O8k= From: Eric Wong To: meta@public-inbox.org Subject: [PATCH 2/3] www: cgit: fall back to WwwCoderepo on 404s Date: Wed, 5 Oct 2022 22:29:40 +0000 Message-Id: <20221005222941.4098-3-e@80x24.org> In-Reply-To: <20221005222941.4098-1-e@80x24.org> References: <20221005222941.4098-1-e@80x24.org> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit List-Id: 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 | 4 ++-- lib/PublicInbox/GitHTTPBackend.pm | 19 ++++++++++++++++--- lib/PublicInbox/Qspawn.pm | 8 ++++---- 3 files changed, 22 insertions(+), 9 deletions(-) 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