about summary refs log tree commit homepage
diff options
context:
space:
mode:
authorEric Wong <e@80x24.org>2019-12-25 07:50:47 +0000
committerEric Wong <e@80x24.org>2019-12-26 10:48:19 +0000
commita7949988f7f8690c868d2150fe3000fcf6a6d5f4 (patch)
tree71c6782191d29573c4e2b025eb4b6d81deddd7ff
parent3eba4cbd05b348622e772889b06a5994ba69d157 (diff)
downloadpublic-inbox-a7949988f7f8690c868d2150fe3000fcf6a6d5f4.tar.gz
Callers can supply an arg to parse_hdr, now, eliminating the
need for closures to capture local variables.
-rw-r--r--lib/PublicInbox/Cgit.pm12
-rw-r--r--lib/PublicInbox/GitHTTPBackend.pm12
-rw-r--r--lib/PublicInbox/Qspawn.pm7
-rw-r--r--lib/PublicInbox/ViewVCS.pm48
4 files changed, 44 insertions, 35 deletions
diff --git a/lib/PublicInbox/Cgit.pm b/lib/PublicInbox/Cgit.pm
index 353f4162..094f146e 100644
--- a/lib/PublicInbox/Cgit.pm
+++ b/lib/PublicInbox/Cgit.pm
@@ -95,6 +95,12 @@ my @PASS_ENV = qw(
 );
 # XXX: cgit filters may care about more variables...
 
+sub cgit_parse_hdr { # {parse_hdr} for Qspawn
+        my ($r, $bref) = @_;
+        my $res = parse_cgi_headers($r, $bref) or return; # incomplete
+        $res;
+}
+
 sub call {
         my ($self, $env) = @_;
         my $path_info = $env->{PATH_INFO};
@@ -123,11 +129,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_config}->limiter('-cgit');
-        $qsp->psgi_return($env, $limiter, sub {
-                my ($r, $bref) = @_;
-                my $res = parse_cgi_headers($r, $bref) or return; # incomplete
-                $res;
-        });
+        $qsp->psgi_return($env, $limiter, \&cgit_parse_hdr);
 }
 
 1;
diff --git a/lib/PublicInbox/GitHTTPBackend.pm b/lib/PublicInbox/GitHTTPBackend.pm
index ec8e6516..537a1947 100644
--- a/lib/PublicInbox/GitHTTPBackend.pm
+++ b/lib/PublicInbox/GitHTTPBackend.pm
@@ -184,6 +184,12 @@ sub prepare_range {
         ($code, $len);
 }
 
+sub git_parse_hdr { # {parse_hdr} for Qspawn
+        my ($r, $bref, $dumb_args) = @_;
+        my $res = parse_cgi_headers($r, $bref) or return; # incomplete
+        $res->[0] == 403 ? serve_dumb(@$dumb_args) : $res;
+}
+
 # returns undef if 403 so it falls back to dumb HTTP
 sub serve_smart {
         my ($env, $git, $path) = @_;
@@ -204,11 +210,7 @@ sub serve_smart {
         $env{PATH_TRANSLATED} = "$git->{git_dir}/$path";
         my $rdr = input_prepare($env) or return r(500);
         my $qsp = PublicInbox::Qspawn->new([qw(git http-backend)], \%env, $rdr);
-        $qsp->psgi_return($env, $limiter, sub { # parse_hdr
-                my ($r, $bref) = @_;
-                my $res = parse_cgi_headers($r, $bref) or return; # incomplete
-                $res->[0] == 403 ? serve_dumb($env, $git, $path) : $res;
-        });
+        $qsp->psgi_return($env, $limiter, \&git_parse_hdr, [$env, $git, $path]);
 }
 
 sub input_prepare {
diff --git a/lib/PublicInbox/Qspawn.pm b/lib/PublicInbox/Qspawn.pm
index d1a34bea..1a2b70e7 100644
--- a/lib/PublicInbox/Qspawn.pm
+++ b/lib/PublicInbox/Qspawn.pm
@@ -215,12 +215,13 @@ sub rd_hdr ($) {
         my $ret;
         my $total_rd = 0;
         my $hdr_buf = $self->{hdr_buf};
+        my ($ph_cb, $ph_arg) = @{$self->{parse_hdr}};
         do {
                 my $r = sysread($self->{rpipe}, $$hdr_buf, 4096,
                                 length($$hdr_buf));
                 if (defined($r)) {
                         $total_rd += $r;
-                        $ret = $self->{parse_hdr}->($total_rd, $hdr_buf);
+                        $ret = $ph_cb->($total_rd, $hdr_buf, $ph_arg);
                 } else {
                         # caller should notify us when it's ready:
                         return if $! == EAGAIN;
@@ -298,10 +299,10 @@ sub psgi_return_start { # may run later, much later...
 #              psgix.io.  3-element arrays means the body is available
 #              immediately (or streamed via ->getline (pull-based)).
 sub psgi_return {
-        my ($self, $env, $limiter, $parse_hdr) = @_;
+        my ($self, $env, $limiter, $parse_hdr, $hdr_arg) = @_;
         $self->{psgi_env} = $env;
         $self->{hdr_buf} = \(my $hdr_buf = '');
-        $self->{parse_hdr} = $parse_hdr;
+        $self->{parse_hdr} = [ $parse_hdr, $hdr_arg ];
         $limiter ||= $def_limiter ||= PublicInbox::Qspawn::Limiter->new(32);
 
         # the caller already captured the PSGI write callback from
diff --git a/lib/PublicInbox/ViewVCS.pm b/lib/PublicInbox/ViewVCS.pm
index 886e10cb..7618b198 100644
--- a/lib/PublicInbox/ViewVCS.pm
+++ b/lib/PublicInbox/ViewVCS.pm
@@ -42,35 +42,39 @@ sub html_page ($$$) {
         $wcb ? $wcb->($res) : $res;
 }
 
+sub stream_blob_parse_hdr { # {parse_hdr} for Qspawn
+        my ($r, $bref, $ctx) = @_;
+        my ($res, $logref) = delete @$ctx{qw(-res -logref)};
+        my ($git, $oid, $type, $size, $di) = @$res;
+        my @cl = ('Content-Length', $size);
+        if (!defined $r) { # error
+                html_page($ctx, 500, $logref);
+        } elsif (index($$bref, "\0") >= 0) {
+                [200, [qw(Content-Type application/octet-stream), @cl] ];
+        } else {
+                my $n = bytes::length($$bref);
+                if ($n >= $BIN_DETECT || $n == $size) {
+                        return [200, [ 'Content-Type',
+                                'text/plain; charset=UTF-8', @cl ] ];
+                }
+                if ($r == 0) {
+                        warn "premature EOF on $oid $$logref\n";
+                        return html_page($ctx, 500, $logref);
+                }
+                undef; # bref keeps growing
+        }
+}
+
 sub stream_large_blob ($$$$) {
         my ($ctx, $res, $logref, $fn) = @_;
+        $ctx->{-logref} = $logref;
+        $ctx->{-res} = $res;
         my ($git, $oid, $type, $size, $di) = @$res;
         my $cmd = ['git', "--git-dir=$git->{git_dir}", 'cat-file', $type, $oid];
         my $qsp = PublicInbox::Qspawn->new($cmd);
-        my @cl = ('Content-Length', $size);
         my $env = $ctx->{env};
-        $env->{'public-inbox.tmpgit'} = $git; # for {-tmp}/File::Temp::Dir
         $env->{'qspawn.wcb'} = delete $ctx->{-wcb};
-        $qsp->psgi_return($env, undef, sub {
-                my ($r, $bref) = @_;
-                if (!defined $r) { # error
-                        html_page($ctx, 500, $logref);
-                } elsif (index($$bref, "\0") >= 0) {
-                        my $ct = 'application/octet-stream';
-                        [200, ['Content-Type', $ct, @cl ] ];
-                } else {
-                        my $n = bytes::length($$bref);
-                        if ($n >= $BIN_DETECT || $n == $size) {
-                                my $ct = 'text/plain; charset=UTF-8';
-                                return [200, ['Content-Type', $ct, @cl] ];
-                        }
-                        if ($r == 0) {
-                                warn "premature EOF on $oid $$logref\n";
-                                return html_page($ctx, 500, $logref);
-                        }
-                        undef; # bref keeps growing
-                }
-        });
+        $qsp->psgi_return($env, undef, \&stream_blob_parse_hdr, $ctx);
 }
 
 sub show_other_result ($$) {